root/src/modules/lua.c

Revision 6210da7ee0e2ed143d71a8e00b709f16e71059f8, 22.0 kB (checked in by Theo Schlossnagle <jesus@omniti.com>, 5 years ago)

various changes to avoid dereferencing type-punned pointers and breaking strict-aliasing rules, refs #34

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