Apache HTTPD
lua_vmprep.c
Go to the documentation of this file.
1
17#include "mod_lua.h"
18#include "http_log.h"
19#include "apr_uuid.h"
20#include "lua_config.h"
21#include "apr_file_info.h"
22#include "mod_auth.h"
23
25
26#ifndef AP_LUA_MODULE_EXT
27#if defined(NETWARE)
28#define AP_LUA_MODULE_EXT ".nlm"
29#elif defined(WIN32)
30#define AP_LUA_MODULE_EXT ".dll"
31#elif (defined(__hpux__) || defined(__hpux)) && !defined(__ia64)
32#define AP_LUA_MODULE_EXT ".sl"
33#else
34#define AP_LUA_MODULE_EXT ".so"
35#endif
36#endif
37
38#if APR_HAS_THREADS
40#endif
42
44{
45 apr_status_t rv;
46
47 /* global IVM mutex */
50 pool);
51 if (rv != APR_SUCCESS) {
53 "mod_lua: Failed to reopen mutex lua-ivm-shm in child");
54 exit(1); /* bah :( */
55 }
56
57 /* Server pool mutex */
58#if APR_HAS_THREADS
60#endif
61}
62
63/* forward dec'l from this file */
64
65#if 0
66static void pstack_dump(lua_State *L, apr_pool_t *r, int level,
67 const char *msg)
68{
69 int i;
70 int top = lua_gettop(L);
71
72 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03211)
73 "Lua Stack Dump: [%s]", msg);
74
75 for (i = 1; i <= top; i++) {
76 int t = lua_type(L, i);
77 switch (t) {
78 case LUA_TSTRING:{
79 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03212)
80 "%d: '%s'", i, lua_tostring(L, i));
81 break;
82 }
83 case LUA_TUSERDATA:{
84 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03213)
85 "%d: userdata", i);
86 break;
87 }
89 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03214)
90 "%d: lightuserdata", i);
91 break;
92 }
93 case LUA_TNIL:{
94 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03215)
95 "%d: NIL", i);
96 break;
97 }
98 case LUA_TNONE:{
99 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03216)
100 "%d: None", i);
101 break;
102 }
103 case LUA_TBOOLEAN:{
104 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03217)
105 "%d: %s",
106 i, lua_toboolean(L, i) ? "true" : "false");
107 break;
108 }
109 case LUA_TNUMBER:{
110 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03218)
111 "%d: %g", i, lua_tonumber(L, i));
112 break;
113 }
114 case LUA_TTABLE:{
115 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03219)
116 "%d: <table>", i);
117 break;
118 }
119 case LUA_TTHREAD:{
120 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03220)
121 "%d: <thread>", i);
122 break;
123 }
124 case LUA_TFUNCTION:{
125 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03221)
126 "%d: <function>", i);
127 break;
128 }
129 default:{
130 ap_log_perror(APLOG_MARK, level, 0, r, APLOGNO(03222)
131 "%d: unknown: [%s]", i, lua_typename(L, i));
132 break;
133 }
134 }
135 }
136}
137#endif
138
139/* BEGIN modules*/
140
141/* BEGIN apache lmodule */
142
143#define makeintegerfield(L, n) lua_pushinteger(L, n); lua_setfield(L, -2, #n)
144
146{
147 lua_getglobal(L, "package");
148 lua_getfield(L, -1, "loaded");
149 lua_newtable(L);
150 lua_setfield(L, -2, "apache2");
151 lua_setglobal(L, "apache2");
152 lua_pop(L, 1); /* empty stack */
153
154 lua_getglobal(L, "apache2");
155
157 lua_setfield(L, -2, "version");
158
173
174 /*
175 makeintegerfield(L, HTTP_CONTINUE);
176 makeintegerfield(L, HTTP_SWITCHING_PROTOCOLS);
177 makeintegerfield(L, HTTP_PROCESSING);
178 makeintegerfield(L, HTTP_OK);
179 makeintegerfield(L, HTTP_CREATED);
180 makeintegerfield(L, HTTP_ACCEPTED);
181 makeintegerfield(L, HTTP_NON_AUTHORITATIVE);
182 makeintegerfield(L, HTTP_NO_CONTENT);
183 makeintegerfield(L, HTTP_RESET_CONTENT);
184 makeintegerfield(L, HTTP_PARTIAL_CONTENT);
185 makeintegerfield(L, HTTP_MULTI_STATUS);
186 makeintegerfield(L, HTTP_ALREADY_REPORTED);
187 makeintegerfield(L, HTTP_IM_USED);
188 makeintegerfield(L, HTTP_MULTIPLE_CHOICES);
189 makeintegerfield(L, HTTP_MOVED_PERMANENTLY);
190 makeintegerfield(L, HTTP_MOVED_TEMPORARILY);
191 makeintegerfield(L, HTTP_SEE_OTHER);
192 makeintegerfield(L, HTTP_NOT_MODIFIED);
193 makeintegerfield(L, HTTP_USE_PROXY);
194 makeintegerfield(L, HTTP_TEMPORARY_REDIRECT);
195 makeintegerfield(L, HTTP_PERMANENT_REDIRECT);
196 makeintegerfield(L, HTTP_BAD_REQUEST);
197 makeintegerfield(L, HTTP_UNAUTHORIZED);
198 makeintegerfield(L, HTTP_PAYMENT_REQUIRED);
199 makeintegerfield(L, HTTP_FORBIDDEN);
200 makeintegerfield(L, HTTP_NOT_FOUND);
201 makeintegerfield(L, HTTP_METHOD_NOT_ALLOWED);
202 makeintegerfield(L, HTTP_NOT_ACCEPTABLE);
203 makeintegerfield(L, HTTP_PROXY_AUTHENTICATION_REQUIRED);
204 makeintegerfield(L, HTTP_REQUEST_TIME_OUT);
205 makeintegerfield(L, HTTP_CONFLICT);
206 makeintegerfield(L, HTTP_GONE);
207 makeintegerfield(L, HTTP_LENGTH_REQUIRED);
208 makeintegerfield(L, HTTP_PRECONDITION_FAILED);
209 makeintegerfield(L, HTTP_REQUEST_ENTITY_TOO_LARGE);
210 makeintegerfield(L, HTTP_REQUEST_URI_TOO_LARGE);
211 makeintegerfield(L, HTTP_UNSUPPORTED_MEDIA_TYPE);
212 makeintegerfield(L, HTTP_RANGE_NOT_SATISFIABLE);
213 makeintegerfield(L, HTTP_EXPECTATION_FAILED);
214 makeintegerfield(L, HTTP_UNPROCESSABLE_ENTITY);
215 makeintegerfield(L, HTTP_LOCKED);
216 makeintegerfield(L, HTTP_FAILED_DEPENDENCY);
217 makeintegerfield(L, HTTP_UPGRADE_REQUIRED);
218 makeintegerfield(L, HTTP_PRECONDITION_REQUIRED);
219 makeintegerfield(L, HTTP_TOO_MANY_REQUESTS);
220 makeintegerfield(L, HTTP_REQUEST_HEADER_FIELDS_TOO_LARGE);
221 makeintegerfield(L, HTTP_INTERNAL_SERVER_ERROR);
222 makeintegerfield(L, HTTP_NOT_IMPLEMENTED);
223 makeintegerfield(L, HTTP_BAD_GATEWAY);
224 makeintegerfield(L, HTTP_SERVICE_UNAVAILABLE);
225 makeintegerfield(L, HTTP_GATEWAY_TIME_OUT);
226 makeintegerfield(L, HTTP_VERSION_NOT_SUPPORTED);
227 makeintegerfield(L, HTTP_VARIANT_ALSO_VARIES);
228 makeintegerfield(L, HTTP_INSUFFICIENT_STORAGE);
229 makeintegerfield(L, HTTP_LOOP_DETECTED);
230 makeintegerfield(L, HTTP_NOT_EXTENDED);
231 makeintegerfield(L, HTTP_NETWORK_AUTHENTICATION_REQUIRED);
232 */
233}
234
235/* END apache2 lmodule */
236
237/* END library functions */
238
239/* callback for cleaning up a lua vm when pool is closed */
241{
242 AP_DEBUG_ASSERT(l != NULL);
243 lua_close((lua_State *) l);
244 return APR_SUCCESS;
245}
246
248{
250 AP_DEBUG_ASSERT(spec != NULL);
251 if (spec->L != NULL) {
252 lua_close((lua_State *) spec->L);
253 }
254 return APR_SUCCESS;
255}
256
257/*
258 munge_path(L,
259 "path",
260 "?.lua",
261 "./?.lua",
262 lifecycle_pool,
263 spec->package_paths,
264 spec->file);
265*/
274static void munge_path(lua_State *L,
275 const char *field,
276 const char *sub_pat,
277 const char *rep_pat,
280 const char *file)
281{
282 const char *current;
283 const char *parent_dir;
284 const char *pattern;
285 const char *modified;
286 char *part;
287
288 lua_getglobal(L, "package");
289 lua_getfield(L, -1, field);
290
291 current = lua_tostring(L, -1);
292
294
296
297 luaL_gsub(L, current, rep_pat, pattern);
298 lua_setfield(L, -3, field);
299 lua_getfield(L, -2, field);
300 modified = lua_tostring(L, -1);
301
302
303 lua_pop(L, 2);
304
305 part = apr_pstrcat(pool, modified, ";", apr_array_pstrcat(pool, paths, ';'),
306 NULL);
307
309 lua_setfield(L, -2, field);
310 lua_pop(L, 1); /* pop "package" off the stack */
311}
312
313#ifdef AP_ENABLE_LUAJIT
315{
316 lua_getglobal(L, "require");
317 lua_pushliteral(L, "jit.");
318 lua_pushvalue(L, -3);
319 lua_concat(L, 2);
320 if (lua_pcall(L, 1, 1, 0)) {
321 const char *msg = lua_tostring(L, -1);
323 "Failed to init LuaJIT: %s", msg);
324 return 1;
325 }
326 lua_getfield(L, -1, "start");
327 lua_remove(L, -2); /* drop module table */
328 return 0;
329}
330
331#endif
332
334{
335 lua_State* L;
336
337 ap_lua_vm_spec *spec = params;
338
339 L = luaL_newstate();
340#ifdef AP_ENABLE_LUAJIT
341 luaopen_jit(L);
342#endif
343 luaL_openlibs(L);
344 if (spec->package_paths) {
345 munge_path(L,
346 "path", "?.lua", "./?.lua",
348 spec->package_paths,
349 spec->file);
350 }
351 if (spec->package_cpaths) {
352 munge_path(L,
353 "cpath", "?" AP_LUA_MODULE_EXT, "./?" AP_LUA_MODULE_EXT,
355 spec->package_cpaths,
356 spec->file);
357 }
358
359 if (spec->cb) {
360 spec->cb(L, lifecycle_pool, spec->cb_arg);
361 }
362
363
364 if (spec->bytecode && spec->bytecode_len > 0) {
365 luaL_loadbuffer(L, spec->bytecode, spec->bytecode_len, spec->file);
366 lua_pcall(L, 0, LUA_MULTRET, 0);
367 }
368 else {
369 int rc;
371 "loading lua file %s", spec->file);
372 rc = luaL_loadfile(L, spec->file);
373 if (rc != 0) {
375 "Error loading %s: %s", spec->file,
376 rc == LUA_ERRMEM ? "memory allocation error"
377 : lua_tostring(L, 0));
378 return APR_EBADF;
379 }
380 if ( lua_pcall(L, 0, LUA_MULTRET, 0) == LUA_ERRRUN ) {
382 "Error loading %s: %s", spec->file,
383 lua_tostring(L, -1));
384 return APR_EBADF;
385 }
386 }
387
388#ifdef AP_ENABLE_LUAJIT
390#endif
392 lua_setfield(L, LUA_REGISTRYINDEX, "Apache2.Wombat.pool");
393 *vm = L;
394
395 return APR_SUCCESS;
396}
397
399{
401 copied_spec->bytecode_len = spec->bytecode_len;
402 copied_spec->bytecode = apr_pstrdup(pool, spec->bytecode);
403 copied_spec->cb = spec->cb;
404 copied_spec->cb_arg = NULL;
405 copied_spec->file = apr_pstrdup(pool, spec->file);
406 copied_spec->package_cpaths = apr_array_copy(pool, spec->package_cpaths);
407 copied_spec->package_paths = apr_array_copy(pool, spec->package_paths);
408 copied_spec->pool = pool;
410 copied_spec->codecache = spec->codecache;
411 return copied_spec;
412}
413
415{
416 lua_State* L;
418 *resource = NULL;
419 if (vm_construct(&L, params, pool) == APR_SUCCESS) {
420 spec->finfo = apr_pcalloc(pool, sizeof(ap_lua_finfo));
421 if (L != NULL) {
422 spec->L = L;
423 *resource = (void*) spec;
424 lua_pushlightuserdata(L, spec);
425 lua_setfield(L, LUA_REGISTRYINDEX, "Apache2.Lua.server_spec");
426 return APR_SUCCESS;
427 }
428 }
429 return APR_EGENERAL;
430}
431
438{
439 lua_State *L = NULL;
441 int tryCache = 0;
442
443 if (spec->scope == AP_LUA_SCOPE_SERVER) {
444 char *hash;
447 hash = apr_psprintf(r->pool, "reslist:%s", spec->file);
448#if APR_HAS_THREADS
450#endif
451 if (apr_pool_userdata_get((void **)&reslist, hash,
453 if (reslist != NULL) {
454 if (apr_reslist_acquire(reslist, (void**) &sspec) == APR_SUCCESS) {
455 L = sspec->L;
456 cache_info = sspec->finfo;
457 }
458 }
459 }
460 if (L == NULL) {
462 if (
463 apr_reslist_create(&reslist, spec->vm_min, spec->vm_max, spec->vm_max, 0,
467 == APR_SUCCESS && reslist != NULL) {
469 r->server->process->pool);
470 if (apr_reslist_acquire(reslist, (void**) &sspec) == APR_SUCCESS) {
471 L = sspec->L;
472 cache_info = sspec->finfo;
473 }
474 else {
475#if APR_HAS_THREADS
477#endif
478 return NULL;
479 }
480 }
481 }
482#if APR_HAS_THREADS
484#endif
485 }
486 else {
487 if (apr_pool_userdata_get((void **)&L, spec->file,
489 L = NULL;
490 }
491 }
492 if (L == NULL) {
494 "creating lua_State with file %s", spec->file);
495 /* not available, so create */
496
497 if (!vm_construct(&L, spec, lifecycle_pool)) {
498 AP_DEBUG_ASSERT(L != NULL);
500 }
501 }
502
503 if (spec->codecache == AP_LUA_CACHE_FOREVER || (spec->bytecode && spec->bytecode_len > 0)) {
504 tryCache = 1;
505 }
506 else {
507 char* mkey;
508 if (spec->scope != AP_LUA_SCOPE_SERVER) {
509 mkey = apr_psprintf(r->pool, "ap_lua_modified:%s", spec->file);
511 if (cache_info == NULL) {
514 }
515 }
516 if (spec->codecache == AP_LUA_CACHE_STAT) {
519
520 /* On first visit, modified will be zero, but that's fine - The file is
521 loaded in the vm_construct function.
522 */
523 if ((cache_info->modified == lua_finfo.mtime && cache_info->size == lua_finfo.size)
524 || cache_info->modified == 0) {
525 tryCache = 1;
526 }
527 cache_info->modified = lua_finfo.mtime;
528 cache_info->size = lua_finfo.size;
529 }
530 else if (spec->codecache == AP_LUA_CACHE_NEVER) {
531 if (cache_info->runs == 0)
532 tryCache = 1;
533 }
534 cache_info->runs++;
535 }
536 if (tryCache == 0 && spec->scope != AP_LUA_SCOPE_ONCE) {
537 int rc;
539 "(re)loading lua file %s", spec->file);
540 rc = luaL_loadfile(L, spec->file);
541 if (rc != 0) {
543 "Error loading %s: %s", spec->file,
544 rc == LUA_ERRMEM ? "memory allocation error"
545 : lua_tostring(L, 0));
546 return 0;
547 }
548 lua_pcall(L, 0, LUA_MULTRET, 0);
549 }
550
551 return L;
552}
const char * pattern
Definition ap_regex.h:243
APR File Information.
#define hash(h, r, b, n)
Definition apr_random.c:51
APR UUID library.
#define APLOG_USE_MODULE(foo)
request_rec * r
#define DECLINED
Definition httpd.h:457
#define OK
Definition httpd.h:456
#define DONE
Definition httpd.h:458
const char * ap_get_server_banner(void)
Definition core.c:3593
#define APLOGNO(n)
Definition http_log.h:117
#define APLOG_ERR
Definition http_log.h:67
#define ap_log_error
Definition http_log.h:370
#define APLOG_MARK
Definition http_log.h:283
#define ap_log_perror
Definition http_log.h:412
#define APLOG_CRIT
Definition http_log.h:66
#define APLOG_DEBUG
Definition http_log.h:71
#define APR_EGENERAL
Definition apr_errno.h:313
#define APR_EBADF
Definition apr_errno.h:704
apr_pool_t const char * params
Definition apr_dbd.h:141
apr_redis_t * rc
Definition apr_redis.h:173
apr_status_t(* apr_reslist_constructor)(void **resource, void *params, apr_pool_t *pool)
Definition apr_reslist.h:50
apr_status_t(* apr_reslist_destructor)(void *resource, void *params, apr_pool_t *pool)
Definition apr_reslist.h:59
void ** resource
#define HTTP_MOVED_TEMPORARILY
Definition httpd.h:502
#define PROXYREQ_NONE
Definition httpd.h:1133
char * ap_make_dirstr_parent(apr_pool_t *p, const char *s)
Definition util.c:692
#define AP_DEBUG_ASSERT(exp)
Definition httpd.h:2283
#define PROXYREQ_PROXY
Definition httpd.h:1134
#define PROXYREQ_REVERSE
Definition httpd.h:1135
#define PROXYREQ_RESPONSE
Definition httpd.h:1136
apr_size_t size
const char int apr_pool_t * pool
Definition apr_cstr.h:84
#define APR_SUCCESS
Definition apr_errno.h:225
int apr_status_t
Definition apr_errno.h:44
const char apr_file_t * file
#define APR_FINFO_MTIME
#define APR_FINFO_SIZE
apr_interval_time_t t
#define apr_pcalloc(p, size)
Definition apr_pools.h:465
const char * s
Definition apr_strings.h:95
Apache Logging library.
static apr_status_t server_vm_construct(lua_State **resource, void *params, apr_pool_t *pool)
Definition lua_vmprep.c:414
lua_State * ap_lua_get_lua_state(apr_pool_t *lifecycle_pool, ap_lua_vm_spec *spec, request_rec *r)
Definition lua_vmprep.c:436
apr_global_mutex_t * lua_ivm_mutex
Definition mod_lua.c:85
void ap_lua_init_mutex(apr_pool_t *pool, server_rec *s)
Definition lua_vmprep.c:43
#define AP_LUA_MODULE_EXT
Definition lua_vmprep.c:34
static void munge_path(lua_State *L, const char *field, const char *sub_pat, const char *rep_pat, apr_pool_t *pool, apr_array_header_t *paths, const char *file)
Definition lua_vmprep.c:274
void ap_lua_load_apache2_lmodule(lua_State *L)
Definition lua_vmprep.c:145
static apr_status_t cleanup_lua(void *l)
Definition lua_vmprep.c:240
#define makeintegerfield(L, n)
Definition lua_vmprep.c:143
static apr_status_t server_cleanup_lua(void *resource, void *params, apr_pool_t *pool)
Definition lua_vmprep.c:247
static ap_lua_vm_spec * copy_vm_spec(apr_pool_t *pool, ap_lua_vm_spec *spec)
Definition lua_vmprep.c:398
static apr_status_t vm_construct(lua_State **vm, void *params, apr_pool_t *lifecycle_pool)
Definition lua_vmprep.c:333
#define AP_LUA_SCOPE_SERVER
Definition lua_vmprep.h:43
#define AP_LUA_CACHE_FOREVER
Definition lua_vmprep.h:48
#define AP_LUA_SCOPE_ONCE
Definition lua_vmprep.h:39
#define AP_LUA_CACHE_NEVER
Definition lua_vmprep.h:46
#define AP_LUA_CACHE_STAT
Definition lua_vmprep.h:47
Authentication and Authorization Extension for Apache.
@ AUTHZ_DENIED
Definition mod_auth.h:73
@ AUTHZ_GENERAL_ERROR
Definition mod_auth.h:76
@ AUTHZ_DENIED_NO_USER
Definition mod_auth.h:77
@ AUTHZ_NEUTRAL
Definition mod_auth.h:75
@ AUTHZ_GRANTED
Definition mod_auth.h:74
return NULL
Definition mod_so.c:359
int i
Definition mod_so.c:347
ap_lua_finfo * finfo
Definition lua_vmprep.h:115
apr_array_header_t * package_paths
Definition lua_vmprep.h:61
unsigned int vm_max
Definition lua_vmprep.h:70
const char * bytecode
Definition lua_vmprep.h:82
apr_array_header_t * package_cpaths
Definition lua_vmprep.h:62
unsigned int vm_min
Definition lua_vmprep.h:69
apr_size_t bytecode_len
Definition lua_vmprep.h:83
ap_lua_state_open_callback cb
Definition lua_vmprep.h:72
const char * file
Definition lua_vmprep.h:65
apr_pool_t * pool
Definition httpd.h:831
A structure that represents the current request.
Definition httpd.h:845
apr_pool_t * pool
Definition httpd.h:847
server_rec * server
Definition httpd.h:851
A structure to store information for each virtual server.
Definition httpd.h:1322
process_rec * process
Definition httpd.h:1324