Line data Source code
1 :
2 : /*
3 : * Copyright (C) Yichun Zhang (agentzh)
4 : */
5 :
6 :
7 : #ifndef DDEBUG
8 : #define DDEBUG 0
9 : #endif
10 : #include "ddebug.h"
11 :
12 :
13 : #include "ngx_http_lua_directive.h"
14 : #include "ngx_http_lua_logby.h"
15 : #include "ngx_http_lua_exception.h"
16 : #include "ngx_http_lua_util.h"
17 : #include "ngx_http_lua_pcrefix.h"
18 : #include "ngx_http_lua_time.h"
19 : #include "ngx_http_lua_log.h"
20 : #include "ngx_http_lua_regex.h"
21 : #include "ngx_http_lua_cache.h"
22 : #include "ngx_http_lua_headers.h"
23 : #include "ngx_http_lua_variable.h"
24 : #include "ngx_http_lua_string.h"
25 : #include "ngx_http_lua_misc.h"
26 : #include "ngx_http_lua_consts.h"
27 : #include "ngx_http_lua_shdict.h"
28 : #include "ngx_http_lua_util.h"
29 : #include "ngx_http_lua_exception.h"
30 : #if (NGX_HTTP_LUA_HAVE_MALLOC_TRIM)
31 : #include <malloc.h>
32 : #endif
33 :
34 :
35 : static ngx_int_t ngx_http_lua_log_by_chunk(lua_State *L, ngx_http_request_t *r);
36 :
37 :
38 : static void
39 0 : ngx_http_lua_log_by_lua_env(lua_State *L, ngx_http_request_t *r)
40 : {
41 : /* set nginx request pointer to current lua thread's globals table */
42 0 : ngx_http_lua_set_req(L, r);
43 :
44 : /**
45 : * we want to create empty environment for current script
46 : *
47 : * newt = {}
48 : * newt["_G"] = newt
49 : * setmetatable(newt, {__index = _G})
50 : *
51 : * if a function or symbol is not defined in our env, __index will lookup
52 : * in the global env.
53 : *
54 : * all variables created in the script-env will be thrown away at the end
55 : * of the script run.
56 : * */
57 0 : ngx_http_lua_create_new_globals_table(L, 0 /* narr */, 1 /* nrec */);
58 :
59 : /* {{{ make new env inheriting main thread's globals table */
60 0 : lua_createtable(L, 0, 1); /* the metatable for the new env */
61 0 : ngx_http_lua_get_globals_table(L);
62 0 : lua_setfield(L, -2, "__index");
63 0 : lua_setmetatable(L, -2); /* setmetatable({}, {__index = _G}) */
64 : /* }}} */
65 :
66 0 : lua_setfenv(L, -2); /* set new running env for the code closure */
67 0 : }
68 :
69 :
70 : ngx_int_t
71 0 : ngx_http_lua_log_handler(ngx_http_request_t *r)
72 : {
73 : #if (NGX_HTTP_LUA_HAVE_MALLOC_TRIM)
74 : ngx_uint_t trim_cycle, trim_nreq;
75 : ngx_http_lua_main_conf_t *lmcf;
76 : #endif
77 : ngx_http_lua_loc_conf_t *llcf;
78 : ngx_http_lua_ctx_t *ctx;
79 :
80 : #if (NGX_HTTP_LUA_HAVE_MALLOC_TRIM)
81 0 : lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
82 :
83 0 : trim_cycle = lmcf->malloc_trim_cycle;
84 :
85 0 : if (trim_cycle > 0) {
86 :
87 : dd("cycle: %d", (int) trim_cycle);
88 :
89 0 : trim_nreq = ++lmcf->malloc_trim_req_count;
90 :
91 0 : if (trim_nreq >= trim_cycle) {
92 0 : lmcf->malloc_trim_req_count = 0;
93 :
94 : #if (NGX_DEBUG)
95 0 : ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
96 : "malloc_trim(1) returned %d", malloc_trim(1));
97 : #else
98 : (void) malloc_trim(1);
99 : #endif
100 : }
101 : }
102 : # if (NGX_DEBUG)
103 : else {
104 0 : ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
105 : "malloc_trim() disabled");
106 : }
107 : # endif
108 : #endif
109 :
110 0 : ngx_log_debug2(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
111 : "lua log handler, uri:\"%V\" c:%ud", &r->uri,
112 : r->main->count);
113 :
114 0 : llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
115 :
116 0 : if (llcf->log_handler == NULL) {
117 : dd("no log handler found");
118 0 : return NGX_DECLINED;
119 : }
120 :
121 0 : ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
122 :
123 : dd("ctx = %p", ctx);
124 :
125 0 : if (ctx == NULL) {
126 0 : ctx = ngx_http_lua_create_ctx(r);
127 0 : if (ctx == NULL) {
128 0 : return NGX_ERROR;
129 : }
130 : }
131 :
132 0 : ctx->context = NGX_HTTP_LUA_CONTEXT_LOG;
133 :
134 : dd("calling log handler");
135 0 : return llcf->log_handler(r);
136 : }
137 :
138 :
139 : ngx_int_t
140 0 : ngx_http_lua_log_handler_inline(ngx_http_request_t *r)
141 : {
142 : lua_State *L;
143 : ngx_int_t rc;
144 : ngx_http_lua_loc_conf_t *llcf;
145 :
146 : dd("log by lua inline");
147 :
148 0 : llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
149 :
150 0 : L = ngx_http_lua_get_lua_vm(r, NULL);
151 :
152 : /* load Lua inline script (w/ cache) sp = 1 */
153 0 : rc = ngx_http_lua_cache_loadbuffer(r->connection->log, L,
154 0 : llcf->log_src.value.data,
155 : llcf->log_src.value.len,
156 0 : llcf->log_src_key,
157 0 : (const char *) llcf->log_chunkname);
158 0 : if (rc != NGX_OK) {
159 0 : return NGX_ERROR;
160 : }
161 :
162 0 : return ngx_http_lua_log_by_chunk(L, r);
163 : }
164 :
165 :
166 : ngx_int_t
167 0 : ngx_http_lua_log_handler_file(ngx_http_request_t *r)
168 : {
169 : lua_State *L;
170 : ngx_int_t rc;
171 : u_char *script_path;
172 : ngx_http_lua_loc_conf_t *llcf;
173 : ngx_str_t eval_src;
174 :
175 0 : llcf = ngx_http_get_module_loc_conf(r, ngx_http_lua_module);
176 :
177 0 : if (ngx_http_complex_value(r, &llcf->log_src, &eval_src) != NGX_OK) {
178 0 : return NGX_ERROR;
179 : }
180 :
181 0 : script_path = ngx_http_lua_rebase_path(r->pool, eval_src.data,
182 : eval_src.len);
183 :
184 0 : if (script_path == NULL) {
185 0 : return NGX_ERROR;
186 : }
187 :
188 0 : L = ngx_http_lua_get_lua_vm(r, NULL);
189 :
190 : /* load Lua script file (w/ cache) sp = 1 */
191 0 : rc = ngx_http_lua_cache_loadfile(r->connection->log, L, script_path,
192 0 : llcf->log_src_key);
193 0 : if (rc != NGX_OK) {
194 0 : return NGX_ERROR;
195 : }
196 :
197 0 : return ngx_http_lua_log_by_chunk(L, r);
198 : }
199 :
200 :
201 : ngx_int_t
202 0 : ngx_http_lua_log_by_chunk(lua_State *L, ngx_http_request_t *r)
203 : {
204 : ngx_int_t rc;
205 : u_char *err_msg;
206 : size_t len;
207 : #if (NGX_PCRE)
208 : ngx_pool_t *old_pool;
209 : #endif
210 :
211 : /* set Lua VM panic handler */
212 0 : lua_atpanic(L, ngx_http_lua_atpanic);
213 :
214 0 : NGX_LUA_EXCEPTION_TRY {
215 :
216 : /* initialize nginx context in Lua VM, code chunk at stack top sp = 1 */
217 0 : ngx_http_lua_log_by_lua_env(L, r);
218 :
219 : #if (NGX_PCRE)
220 : /* XXX: work-around to nginx regex subsystem */
221 0 : old_pool = ngx_http_lua_pcre_malloc_init(r->pool);
222 : #endif
223 :
224 0 : lua_pushcfunction(L, ngx_http_lua_traceback);
225 0 : lua_insert(L, 1); /* put it under chunk and args */
226 :
227 : /* protected call user code */
228 0 : rc = lua_pcall(L, 0, 1, 1);
229 :
230 0 : lua_remove(L, 1); /* remove traceback function */
231 :
232 : #if (NGX_PCRE)
233 : /* XXX: work-around to nginx regex subsystem */
234 0 : ngx_http_lua_pcre_malloc_done(old_pool);
235 : #endif
236 :
237 0 : if (rc != 0) {
238 : /* error occurred when running loaded code */
239 0 : err_msg = (u_char *) lua_tolstring(L, -1, &len);
240 :
241 0 : if (err_msg == NULL) {
242 0 : err_msg = (u_char *) "unknown reason";
243 0 : len = sizeof("unknown reason") - 1;
244 : }
245 :
246 0 : ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
247 : "failed to run log_by_lua*: %*s", len, err_msg);
248 :
249 0 : lua_settop(L, 0); /* clear remaining elems on stack */
250 :
251 0 : return NGX_ERROR;
252 : }
253 :
254 : } NGX_LUA_EXCEPTION_CATCH {
255 :
256 : dd("nginx execution restored");
257 0 : return NGX_ERROR;
258 : }
259 :
260 : /* clear Lua stack */
261 0 : lua_settop(L, 0);
262 :
263 0 : return NGX_OK;
264 : }
265 :
266 : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */
|