root/src/modules/lua.c

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

bad free of stack value

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