root/src/modules/lua.c

Revision d221460a632fc089092b34dcfb215f8296a9b713, 20.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 6 years ago)

supposedly garbage collecting the coro should be enough to do the trick -- resuming it causes accessing freed memory (due to the gc), refs #47

  • Property mode set to 100644
Line 
1 /*
2  * Copyright (c) 2007, OmniTI Computer Consulting, Inc.
3  * All rights reserved.
4  */
5
6 #include "noit_defines.h"
7
8 #include "noit_conf.h"
9 #include "noit_module.h"
10 #include "noit_check.h"
11 #include "noit_check_tools.h"
12 #include "utils/noit_log.h"
13 #include "lua_noit.h"
14
15 #ifdef HAVE_ALLOCA_H
16 #include <alloca.h>
17 #endif
18 #include <assert.h>
19
20 static noit_log_stream_t nlerr = NULL;
21 static noit_log_stream_t nldeb = NULL;
22 static noit_hash_table noit_coros = NOIT_HASH_EMPTY;
23
24 struct loader_conf {
25   char *script_dir;
26 };
27 static struct loader_conf *__get_loader_conf(noit_module_loader_t *self) {
28   struct loader_conf *c;
29   c = noit_image_get_userdata(&self->hdr);
30   if(!c) {
31     c = calloc(1, sizeof(*c));
32     noit_image_set_userdata(&self->hdr, c);
33   }
34   return c;
35 }
36 static void
37 noit_lua_loader_set_directory(noit_module_loader_t *self, char *dir) {
38   struct loader_conf *c = __get_loader_conf(self);
39   if(c->script_dir) free(c->script_dir);
40   c->script_dir = strdup(dir);
41 }
42 static const char *
43 noit_lua_loader_get_directory(noit_module_loader_t *self) {
44   struct loader_conf *c = __get_loader_conf(self);
45   return c->script_dir;
46 }
47
48 void
49 cancel_coro(noit_lua_check_info_t *ci) {
50   lua_getglobal(ci->lmc->lua_state, "noit_coros");
51   luaL_unref(ci->lmc->lua_state, -1, ci->coro_state_ref);
52   lua_pop(ci->lmc->lua_state, 1);
53   lua_gc(ci->lmc->lua_state, LUA_GCCOLLECT, 0);
54   noit_hash_delete(&noit_coros,
55                    (const char *)&ci->coro_state, sizeof(ci->coro_state),
56                    NULL, NULL);
57 }
58
59 noit_lua_check_info_t *
60 get_ci(lua_State *L) {
61   noit_lua_check_info_t *v = NULL;
62   if(noit_hash_retrieve(&noit_coros, (const char *)&L, sizeof(L), (void **)&v))
63     return v;
64   return NULL;
65 }
66 static void
67 int_cl_free(void *vcl) {
68   free(vcl);
69 }
70
71 static void
72 noit_event_dispose(void *ev) {
73   int mask;
74   eventer_t *value = ev;
75   eventer_t removed, e = *value;
76   noitL(nldeb, "lua check cleanup: dropping (%p)->fd (%d)\n", e, e->fd);
77   if(e->mask & (EVENTER_READ|EVENTER_WRITE|EVENTER_EXCEPTION)) {
78     noitL(nldeb, "    closing down fd %d\n", e->fd);
79     e->opset->close(e->fd, &mask, e);
80   }
81   removed = eventer_remove(e);
82   noitL(nldeb, "    remove from eventer system %s\n",
83         removed ? "succeeded" : "failed");
84   if(e->closure) {
85     struct nl_generic_cl *cl;
86     cl = e->closure;
87     if(cl->free) cl->free(cl);
88   }
89   eventer_free(e);
90   free(ev);
91 }
92 void
93 noit_lua_check_register_event(noit_lua_check_info_t *ci, eventer_t e) {
94   eventer_t *eptr;
95   eptr = calloc(1, sizeof(*eptr));
96   memcpy(eptr, &e, sizeof(*eptr));
97   if(!ci->events) ci->events = calloc(1, sizeof(*ci->events));
98   assert(noit_hash_store(ci->events, (const char *)eptr, sizeof(*eptr), eptr));
99 }
100 void
101 noit_lua_check_deregister_event(noit_lua_check_info_t *ci, eventer_t e,
102                                 int tofree) {
103   assert(ci->events);
104   assert(noit_hash_delete(ci->events, (const char *)&e, sizeof(e),
105                           NULL, tofree ? noit_event_dispose : free));
106 }
107 void
108 noit_lua_check_clean_events(noit_lua_check_info_t *ci) {
109   noit_hash_destroy(ci->events, NULL, noit_event_dispose);
110   free(ci->events);
111   ci->events = NULL;
112 }
113
114 static void
115 noit_lua_pushmodule(lua_State *L, const char *m) {
116   int stack_pos = LUA_GLOBALSINDEX;
117   char *copy, *part, *brkt;
118   copy = alloca(strlen(m)+1);
119   assert(copy);
120   memcpy(copy,m,strlen(m)+1);
121
122   for(part = strtok_r(copy, ".", &brkt);
123       part;
124       part = strtok_r(NULL, ".", &brkt)) {
125     lua_getfield(L, stack_pos, part);
126     if(stack_pos == -1) lua_remove(L, -2);
127     else stack_pos = -1;
128   }
129 }
130 static void
131 noit_lua_hash_to_table(lua_State *L,
132                        noit_hash_table *t) {
133   noit_hash_iter iter = NOIT_HASH_ITER_ZERO;
134   const char *key, *value;
135   int klen;
136   lua_createtable(L, 0, t ? t->size : 0);
137   if(t) {
138     while(noit_hash_next(t, &iter, &key, &klen, (void **)&value)) {
139       lua_pushlstring(L, value, strlen(value));
140       lua_setfield(L, -2, key);
141     }
142   }
143   return;
144 }
145 static int
146 noit_module_index_func(lua_State *L) {
147   int n;
148   n = lua_gettop(L);    /* number of arguments */
149   assert(n == 2);
150   if(!luaL_checkudata(L, 1, "noit_module_t")) {
151     luaL_error(L, "metatable error, arg1 not a noit_module_t!");
152   }
153   return 0;
154 }
155 static int
156 noit_lua_set_available(lua_State *L) {
157   noit_check_t *check;
158   noit_lua_check_info_t *ci;
159   if(lua_gettop(L)) luaL_error(L, "wrong number of arguments");
160   check = lua_touserdata(L, lua_upvalueindex(1));
161   ci = check->closure;
162   ci->current.available = lua_tointeger(L, lua_upvalueindex(2));
163   return 0;
164 }
165 static int
166 noit_lua_set_state(lua_State *L) {
167   noit_check_t *check;
168   noit_lua_check_info_t *ci;
169   if(lua_gettop(L)) luaL_error(L, "wrong number of arguments");
170   check = lua_touserdata(L, lua_upvalueindex(1));
171   ci = check->closure;
172   ci->current.state = lua_tointeger(L, lua_upvalueindex(2));
173   return 0;
174 }
175 static int
176 noit_lua_set_status(lua_State *L) {
177   noit_check_t *check;
178   noit_lua_check_info_t *ci;
179   if(lua_gettop(L) != 1) luaL_error(L, "wrong number of arguments");
180   check = lua_touserdata(L, lua_upvalueindex(1));
181   ci = check->closure;
182   /* strdup here... but free later */
183   if(ci->current.status) free(ci->current.status);
184   ci->current.status = strdup(lua_tostring(L, 1));
185   return 0;
186 }
187 static int
188 noit_lua_set_metric(lua_State *L) {
189   noit_check_t *check;
190   noit_lua_check_info_t *ci;
191   const char *metric_name;
192   metric_type_t metric_type;
193
194   double __n;
195   int32_t __i;
196   u_int32_t __I;
197   int64_t __l;
198   u_int64_t __L;
199
200   if(lua_gettop(L) != 2) luaL_error(L, "wrong number of arguments");
201   check = lua_touserdata(L, lua_upvalueindex(1));
202   ci = check->closure;
203   if(!lua_isstring(L, 1)) luaL_error(L, "argument #1 must be a string");
204   metric_name = lua_tostring(L, 1);
205   metric_type = lua_tointeger(L, lua_upvalueindex(2));
206   if(lua_isnil(L, 2)) {
207     noit_stats_set_metric(&ci->current, metric_name, metric_type, NULL);
208     return 0;
209   }
210   switch(metric_type) {
211     case METRIC_GUESS:
212     case METRIC_STRING:
213       noit_stats_set_metric(&ci->current, metric_name, metric_type,
214                             (void *)lua_tostring(L, 2));
215       break;
216     case METRIC_INT32:
217       __i = luaL_optinteger(L, 2, 0);
218       noit_stats_set_metric(&ci->current, metric_name, metric_type, &__i);
219       break;
220     case METRIC_UINT32:
221       __I = luaL_optinteger(L, 2, 0);
222       noit_stats_set_metric(&ci->current, metric_name, metric_type, &__I);
223       break;
224     case METRIC_INT64:
225       __l = luaL_optinteger(L, 2, 0);
226       noit_stats_set_metric(&ci->current, metric_name, metric_type, &__l);
227       break;
228     case METRIC_UINT64:
229       __L = luaL_optinteger(L, 2, 0);
230       noit_stats_set_metric(&ci->current, metric_name, metric_type, &__L);
231       break;
232     case METRIC_DOUBLE:
233       __n = luaL_optnumber(L, 2, 0);
234       noit_stats_set_metric(&ci->current, metric_name, metric_type, &__n);
235       break;
236   }
237   return 0;
238 }
239 static int
240 noit_check_index_func(lua_State *L) {
241   int n;
242   const char *k;
243   noit_check_t **udata, *check;
244   n = lua_gettop(L);    /* number of arguments */
245   assert(n == 2);
246   if(!luaL_checkudata(L, 1, "noit_check_t")) {
247     luaL_error(L, "metatable error, arg1 not a noit_check_t!");
248   }
249   udata = lua_touserdata(L, 1);
250   check = *udata;
251   if(!lua_isstring(L, 2)) {
252     luaL_error(L, "metatable error, arg2 not a string!");
253   }
254   k = lua_tostring(L, 2);
255   switch(*k) {
256     case 'a':
257       if(!strcmp(k, "available")) {
258         lua_pushlightuserdata(L, check);
259         lua_pushinteger(L, NP_AVAILABLE);
260         lua_pushcclosure(L, noit_lua_set_available, 2);
261       }
262       else break;
263       return 1;
264     case 'b':
265       if(!strcmp(k, "bad")) {
266         lua_pushlightuserdata(L, check);
267         lua_pushinteger(L, NP_BAD);
268         lua_pushcclosure(L, noit_lua_set_state, 2);
269       }
270       else break;
271       return 1;
272     case 'c':
273       if(!strcmp(k, "config")) noit_lua_hash_to_table(L, check->config);
274       else break;
275       return 1;
276     case 'g':
277       if(!strcmp(k, "good")) {
278         lua_pushlightuserdata(L, check);
279         lua_pushinteger(L, NP_GOOD);
280         lua_pushcclosure(L, noit_lua_set_state, 2);
281       }
282       else break;
283       return 1;
284     case 'm':
285       if(!strcmp(k, "module")) lua_pushstring(L, check->module);
286
287 #define IF_METRIC_BLOCK(name,type) \
288       if(!strcmp(k, name)) { \
289         lua_pushlightuserdata(L, check); \
290         lua_pushinteger(L, type); \
291         lua_pushcclosure(L, noit_lua_set_metric, 2); \
292       }
293
294       else IF_METRIC_BLOCK("metric", METRIC_GUESS)
295       else IF_METRIC_BLOCK("metric_string", METRIC_STRING)
296       else IF_METRIC_BLOCK("metric_int32", METRIC_INT32)
297       else IF_METRIC_BLOCK("metric_uint32", METRIC_UINT32)
298       else IF_METRIC_BLOCK("metric_int64", METRIC_INT64)
299       else IF_METRIC_BLOCK("metric_uint64", METRIC_UINT64)
300       else IF_METRIC_BLOCK("metric_double", METRIC_DOUBLE)
301       else break;
302       return 1;
303     case 'n':
304       if(!strcmp(k, "name")) lua_pushstring(L, check->name);
305       else break;
306       return 1;
307     case 'p':
308       if(!strcmp(k, "period")) lua_pushinteger(L, check->period);
309       else break;
310       return 1;
311     case 's':
312       if(!strcmp(k, "status")) {
313         lua_pushlightuserdata(L, check);
314         lua_pushcclosure(L, noit_lua_set_status, 1);
315       }
316       else break;
317       return 1;
318     case 't':
319       if(!strcmp(k, "target")) lua_pushstring(L, check->target);
320       else if(!strcmp(k, "timeout")) lua_pushinteger(L, check->timeout);
321       else break;
322       return 1;
323     case 'u':
324       if(!strcmp(k, "unavailable")) {
325         lua_pushlightuserdata(L, check);
326         lua_pushinteger(L, NP_UNAVAILABLE);
327         lua_pushcclosure(L, noit_lua_set_available, 2);
328       }
329       else break;
330       return 1;
331     default:
332       break;
333   }
334   luaL_error(L, "noit_check_t no such element: %s", k);
335   return 0;
336 }
337 static void
338 noit_lua_setup_module(lua_State *L,
339                       noit_module_t *mod) {
340   noit_module_t **addr;
341   addr = (noit_module_t **)lua_newuserdata(L, sizeof(mod));
342   *addr = mod;
343   if(luaL_newmetatable(L, "noit_module_t") == 1) {
344     lua_pushcclosure(L, noit_module_index_func, 0);
345     lua_setfield(L, -2, "__index");
346   }
347   lua_setmetatable(L, -2);
348 }
349 static void
350 noit_lua_setup_check(lua_State *L,
351                      noit_check_t *check) {
352   noit_check_t **addr;
353   addr = (noit_check_t **)lua_newuserdata(L, sizeof(check));
354   *addr = check;
355   if(luaL_newmetatable(L, "noit_check_t") == 1) {
356     lua_pushcclosure(L, noit_check_index_func, 0);
357     lua_setfield(L, -2, "__index");
358   }
359   lua_setmetatable(L, -2);
360 }
361 static int
362 noit_lua_module_onload(noit_image_t *i) {
363   int rv;
364   lua_State *L;
365   lua_module_closure_t *lmc;
366
367   lmc = noit_image_get_userdata(i);
368   L = lmc->lua_state;
369   lua_getglobal(L, "require");
370   lua_pushstring(L, lmc->object);
371   rv = lua_pcall(L, 1, 1, 0);
372   if(rv) {
373     int i;
374     noitL(nlerr, "lua: %s.onload failed\n", lmc->object);
375     i = lua_gettop(L);
376     if(i>0) {
377       if(lua_isstring(L, i)) {
378         const char *err;
379         size_t len;
380         err = lua_tolstring(L, i, &len);
381         noitL(nlerr, "lua: %s\n", err);
382       }
383     }
384     lua_pop(L,i);
385     return -1;
386   }
387   lua_pop(L, lua_gettop(L));
388
389   noit_lua_pushmodule(L, lmc->object);
390   if(lua_isnil(L, -1)) {
391     lua_pop(L, 1);
392     noitL(nlerr, "lua: no such object %s\n", lmc->object);
393     return -1;
394   }
395   lua_getfield(L, -1, "onload");
396   lua_remove(L, -2);
397   if(!lua_isfunction(L, -1)) {
398     lua_pop(L, 1);
399     /* No onload */
400     return 0;
401   }
402   noit_lua_setup_module(L, (noit_module_t *)i);
403   lua_pcall(L, 1, 1, 0);
404   if(lua_isnumber(L, -1)) {
405     int rv;
406     rv = lua_tointeger(L, -1);
407     lua_pop(L, 1);
408     return rv;
409   }
410   lua_pop(L,1);
411   noitL(nlerr, "%s.onload must return a integer\n", lmc->object);
412   return -1;
413 }
414 #define LMC_DECL(L, mod) \
415   lua_State *L; \
416   lua_module_closure_t *lmc; \
417   lmc = noit_module_get_userdata(mod); \
418   L = lmc->lua_state
419 #define SETUP_CALL(L, func, failure) do { \
420   noit_lua_pushmodule(L, lmc->object); \
421   lua_getfield(L, -1, func); \
422   lua_remove(L, -2); \
423   if(!lua_isfunction(L, -1)) { \
424     lua_pop(L, 1); \
425     failure; \
426   } \
427 } while(0)
428 #define RETURN_INT(L, func) do { \
429   int base = lua_gettop(L); \
430   assert(base == 1); \
431   if(lua_isnumber(L, -1)) { \
432     int rv; \
433     rv = lua_tointeger(L, -1); \
434     lua_pop(L, 1); \
435     return rv; \
436   } \
437   lua_pop(L,1); \
438   noitL(nlerr, "%s.%s must return a integer\n", lmc->object, func); \
439 } while(0)
440
441 static int
442 noit_lua_module_config(noit_module_t *mod,
443                        noit_hash_table *options) {
444   LMC_DECL(L, mod);
445   SETUP_CALL(L, "config", return 0);
446
447   noit_lua_setup_module(L, mod);
448   noit_lua_hash_to_table(L, options);
449   lua_pcall(L, 2, 1, 0);
450
451   RETURN_INT(L, "config");
452   return -1;
453 }
454 static int
455 noit_lua_module_init(noit_module_t *mod) {
456   LMC_DECL(L, mod);
457   SETUP_CALL(L, "init", return 0);
458
459   noit_lua_setup_module(L, mod);
460   lua_pcall(L, 1, 1, 0);
461
462   RETURN_INT(L, "init");
463   return -1;
464 }
465 static void
466 noit_lua_module_cleanup(noit_module_t *mod, noit_check_t *check) {
467   noit_lua_check_info_t *ci = check->closure;
468   LMC_DECL(L, mod);
469   SETUP_CALL(L, "cleanup", goto clean);
470
471   noit_lua_setup_module(L, mod);
472   noit_lua_setup_check(L, check);
473   lua_pcall(L, 2, 0, 0);
474
475  clean:
476   if(ci) {
477     noit_lua_check_clean_events(ci);
478     free(ci);
479     check->closure = NULL;
480   }
481 }
482
483 /* Here is where the magic starts */
484 static void
485 noit_lua_log_results(noit_module_t *self, noit_check_t *check) {
486   noit_lua_check_info_t *ci = check->closure;
487   struct timeval duration;
488   u_int32_t duration_ms;
489
490   gettimeofday(&ci->finish_time, NULL);
491   sub_timeval(ci->finish_time, check->last_fire_time, &duration);
492
493   memcpy(&ci->current.whence, &ci->finish_time, sizeof(ci->current.whence));
494   ci->current.duration = duration.tv_sec * 1000 + duration.tv_usec / 1000;
495   duration_ms = ci->current.duration;
496
497   noit_check_set_stats(self, check, &ci->current);
498   free(ci->current.status);
499 }
500 int
501 noit_lua_yield(noit_lua_check_info_t *ci, int nargs) {
502   noitL(nldeb, "lua: %p yielding\n", ci->coro_state);
503   return lua_yield(ci->coro_state, nargs);
504 }
505 int
506 noit_lua_resume(noit_lua_check_info_t *ci, int nargs) {
507   int result = -1, base;
508   noit_check_t *check;
509   check = ci->check;
510
511   noitL(nldeb, "lua: %p resuming\n", ci->coro_state);
512   result = lua_resume(ci->coro_state, nargs);
513   switch(result) {
514     case 0: /* success */
515       break;
516     case LUA_YIELD: /* The complicated case */
517       /* The person yielding had better setup an event
518        * to wake up the coro...
519        */
520       lua_gc(ci->lmc->lua_state, LUA_GCCOLLECT, 0);
521       goto done;
522     default: /* Errors */
523       noitL(nlerr, "lua resume returned: %d\n", result);
524       ci->current.status = strdup(ci->timed_out ? "timeout" : "unknown error");
525       ci->current.available = NP_UNAVAILABLE;
526       ci->current.state = NP_BAD;
527       base = lua_gettop(ci->coro_state);
528       if(base>0) {
529         if(lua_isstring(ci->coro_state, base)) {
530           const char *err;
531           err = lua_tostring(ci->coro_state, base);
532           if(err) {
533             free(ci->current.status);
534             ci->current.status = (char *)err;
535           }
536         }
537       }
538       break;
539   }
540   cancel_coro(ci);
541
542   noit_lua_log_results(ci->self, ci->check);
543   noit_lua_module_cleanup(ci->self, ci->check);
544   ci = NULL; /* we freed it... explode if someone uses it before we return */
545   check->flags &= ~NP_RUNNING;
546
547  done:
548   return result;
549 }
550 static int
551 noit_lua_check_timeout(eventer_t e, int mask, void *closure,
552                        struct timeval *now) {
553   noit_check_t *check;
554   struct nl_intcl *int_cl = closure;
555   noit_lua_check_info_t *ci = int_cl->ci;
556   check = ci->check;
557   noitL(nldeb, "lua: %p ->check_timeout\n", ci->coro_state);
558   ci->timed_out = 1;
559   noit_lua_check_deregister_event(ci, e, 0);
560   if(ci->coro_state) {
561     /* Our coro is still "in-flight". To fix this we will unreference
562      * it, garbage collect it and then ensure that it failes a resume
563      */
564     cancel_coro(ci);
565   }
566
567   noit_lua_log_results(ci->self, ci->check);
568   noit_lua_module_cleanup(ci->self, ci->check);
569   check->flags &= ~NP_RUNNING;
570
571   if(int_cl->free) int_cl->free(int_cl);
572   return 0;
573 }
574 static int
575 noit_lua_initiate(noit_module_t *self, noit_check_t *check) {
576   LMC_DECL(L, self);
577   struct nl_intcl *int_cl;
578   noit_lua_check_info_t *ci;
579   struct timeval p_int, __now;
580   eventer_t e;
581
582   if(!check->closure) check->closure = calloc(1, sizeof(noit_lua_check_info_t));
583   ci = check->closure;
584
585   /* We cannot be running */
586   assert(!(check->flags & NP_RUNNING));
587   check->flags |= NP_RUNNING;
588
589   ci->self = self;
590   ci->check = check;
591   noit_check_stats_clear(&ci->current);
592
593   gettimeofday(&__now, NULL);
594   memcpy(&check->last_fire_time, &__now, sizeof(__now));
595
596   e = eventer_alloc();
597   e->mask = EVENTER_TIMER;
598   e->callback = noit_lua_check_timeout;
599   /* We wrap this in an alloc so we can blindly free it later */
600   int_cl = calloc(1, sizeof(*int_cl));
601   int_cl->ci = ci;
602   int_cl->free = int_cl_free;
603   e->closure = int_cl;
604   memcpy(&e->whence, &__now, sizeof(__now));
605   p_int.tv_sec = check->timeout / 1000;
606   p_int.tv_usec = (check->timeout % 1000) * 1000;
607   add_timeval(e->whence, p_int, &e->whence);
608   noit_lua_check_register_event(ci, e);
609   eventer_add(e);
610
611   ci->lmc = lmc;
612   lua_getglobal(L, "noit_coros");
613   ci->coro_state = lua_newthread(L);
614   ci->coro_state_ref = luaL_ref(L, -2);
615   lua_pop(L, 1); /* pops noit_coros */
616   noit_hash_store(&noit_coros,
617                   (const char *)&ci->coro_state, sizeof(ci->coro_state),
618                   ci);
619
620   SETUP_CALL(ci->coro_state, "initiate", goto fail);
621   noit_lua_setup_module(ci->coro_state, ci->self);
622   noit_lua_setup_check(ci->coro_state, ci->check);
623   noit_lua_resume(ci, 2);
624
625   return 0;
626
627  fail:
628   noit_lua_log_results(ci->self, ci->check);
629   noit_lua_module_cleanup(ci->self, ci->check);
630   check->flags &= ~NP_RUNNING;
631   return -1;
632 }
633 /* This is the standard wrapper */
634 static int
635 noit_lua_module_initiate_check(noit_module_t *self, noit_check_t *check,
636                                int once, noit_check_t *cause) {
637   if(!check->closure) check->closure = calloc(1, sizeof(noit_lua_check_info_t));
638   INITIATE_CHECK(noit_lua_initiate, self, check);
639   return 0;
640 }
641 static noit_module_t *
642 noit_lua_loader_load(noit_module_loader_t *loader,
643                      char *module_name,
644                      noit_conf_section_t section) {
645   noit_module_t *m;
646   lua_State *L;
647   lua_module_closure_t *lmc;
648   char *object;
649  
650   noitL(nldeb, "Loading lua module: %s\n", module_name);
651   if(noit_conf_get_string(section, "@object", &object) == 0) {
652     noitL(nlerr, "Lua module %s require object attribute.\n", module_name);
653     return NULL;
654   }
655
656   m = noit_blank_module();
657   m->hdr.magic = NOIT_MODULE_MAGIC;
658   m->hdr.version = NOIT_MODULE_ABI_VERSION;
659   m->hdr.name = strdup(module_name);
660   m->hdr.description = strdup("Lua module");
661   m->hdr.onload = noit_lua_module_onload;
662   lmc = calloc(1, sizeof(*lmc));
663   lmc->object = object;
664
665   L = lmc->lua_state = lua_open();
666
667
668   lua_gc(L, LUA_GCSTOP, 0);  /* stop collector during initialization */
669   luaL_openlibs(L);  /* open libraries */
670   luaopen_noit(L);
671   lua_newtable(L);
672   lua_setglobal(L, "noit_coros");
673
674   lua_getfield(L, LUA_GLOBALSINDEX, "package");
675   lua_pushfstring(L, "%s", noit_lua_loader_get_directory(loader));
676   lua_setfield(L, -2, "path");
677   lua_pop(L, 1);
678
679   lua_gc(L, LUA_GCRESTART, 0);
680
681   noit_image_set_userdata(&m->hdr, lmc);
682   if(m->hdr.onload(&m->hdr) == -1) {
683     free(m->hdr.name);
684     free(m->hdr.description);
685     free(lmc->object);
686     free(lmc);
687     /* FIXME: We leak the opaque_handler in the module here... */
688     free(m);
689     return NULL;
690   }
691
692   m->config = noit_lua_module_config;
693   m->init = noit_lua_module_init;
694   m->initiate_check = noit_lua_module_initiate_check;
695   m->cleanup = noit_lua_module_cleanup;
696
697   noit_register_module(m);
698   return m;
699 }
700
701 static int
702 noit_lua_loader_config(noit_module_loader_t *self, noit_hash_table *o) {
703   char *dir = ".";
704   noit_hash_retrieve(o, "directory", strlen("directory"), (void **)&dir);
705   noit_lua_loader_set_directory(self, dir);
706   return 0;
707 }
708 static int
709 noit_lua_loader_onload(noit_image_t *self) {
710   nlerr = noit_log_stream_find("error/serf");
711   nldeb = noit_log_stream_find("debug/serf");
712   if(!nlerr) nlerr = noit_stderr;
713   if(!nldeb) nldeb = noit_debug;
714   return 0;
715 }
716
717 noit_module_loader_t lua = {
718   {
719     NOIT_LOADER_MAGIC,
720     NOIT_LOADER_ABI_VERSION,
721     "lua",
722     "Lua check loader",
723     noit_lua_loader_onload,
724   },
725   noit_lua_loader_config,
726   NULL,
727   noit_lua_loader_load
728 };
Note: See TracBrowser for help on using the browser.