LCOV - code coverage report
Current view: top level - home/build/openresty-1.13.6.1/build/ngx_lua-0.10.11/src - ngx_http_lua_timer.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 12 365 3.3 %
Date: 2020-03-03 04:25:50 Functions: 1 10 10.0 %
Legend: Lines: hit not hit

          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_timer.h"
      14             : #include "ngx_http_lua_util.h"
      15             : #include "ngx_http_lua_contentby.h"
      16             : #include "ngx_http_lua_probe.h"
      17             : 
      18             : 
      19             : typedef struct {
      20             :     void        **main_conf;
      21             :     void        **srv_conf;
      22             :     void        **loc_conf;
      23             : 
      24             :     lua_State    *co;
      25             : 
      26             :     ngx_pool_t   *pool;
      27             : 
      28             :     ngx_listening_t                   *listening;
      29             :     ngx_str_t                          client_addr_text;
      30             : 
      31             :     ngx_http_lua_main_conf_t          *lmcf;
      32             :     ngx_http_lua_vm_state_t           *vm_state;
      33             : 
      34             :     int           co_ref;
      35             :     unsigned      delay:31;
      36             :     unsigned      premature:1;
      37             : } ngx_http_lua_timer_ctx_t;
      38             : 
      39             : 
      40             : static int ngx_http_lua_ngx_timer_at(lua_State *L);
      41             : static int ngx_http_lua_ngx_timer_every(lua_State *L);
      42             : static int ngx_http_lua_ngx_timer_helper(lua_State *L, int every);
      43             : static int ngx_http_lua_ngx_timer_running_count(lua_State *L);
      44             : static int ngx_http_lua_ngx_timer_pending_count(lua_State *L);
      45             : static ngx_int_t ngx_http_lua_timer_copy(ngx_http_lua_timer_ctx_t *old_tctx);
      46             : static void ngx_http_lua_timer_handler(ngx_event_t *ev);
      47             : static u_char *ngx_http_lua_log_timer_error(ngx_log_t *log, u_char *buf,
      48             :     size_t len);
      49             : static void ngx_http_lua_abort_pending_timers(ngx_event_t *ev);
      50             : 
      51             : 
      52             : void
      53          18 : ngx_http_lua_inject_timer_api(lua_State *L)
      54             : {
      55          18 :     lua_createtable(L, 0 /* narr */, 4 /* nrec */);    /* ngx.timer. */
      56             : 
      57          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_timer_at);
      58          18 :     lua_setfield(L, -2, "at");
      59             : 
      60          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_timer_every);
      61          18 :     lua_setfield(L, -2, "every");
      62             : 
      63          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_timer_running_count);
      64          18 :     lua_setfield(L, -2, "running_count");
      65             : 
      66          18 :     lua_pushcfunction(L, ngx_http_lua_ngx_timer_pending_count);
      67          18 :     lua_setfield(L, -2, "pending_count");
      68             : 
      69          18 :     lua_setfield(L, -2, "timer");
      70          18 : }
      71             : 
      72             : 
      73             : static int
      74           0 : ngx_http_lua_ngx_timer_running_count(lua_State *L)
      75             : {
      76             :     ngx_http_request_t          *r;
      77             :     ngx_http_lua_main_conf_t    *lmcf;
      78             : 
      79           0 :     r = ngx_http_lua_get_req(L);
      80           0 :     if (r == NULL) {
      81           0 :         return luaL_error(L, "no request");
      82             :     }
      83             : 
      84           0 :     lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
      85             : 
      86           0 :     lua_pushnumber(L, lmcf->running_timers);
      87             : 
      88           0 :     return 1;
      89             : }
      90             : 
      91             : 
      92             : static int
      93           0 : ngx_http_lua_ngx_timer_pending_count(lua_State *L)
      94             : {
      95             :     ngx_http_request_t          *r;
      96             :     ngx_http_lua_main_conf_t    *lmcf;
      97             : 
      98           0 :     r = ngx_http_lua_get_req(L);
      99           0 :     if (r == NULL) {
     100           0 :         return luaL_error(L, "no request");
     101             :     }
     102             : 
     103           0 :     lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
     104             : 
     105           0 :     lua_pushnumber(L, lmcf->pending_timers);
     106             : 
     107           0 :     return 1;
     108             : }
     109             : 
     110             : 
     111             : static int
     112           0 : ngx_http_lua_ngx_timer_at(lua_State *L)
     113             : {
     114           0 :     return ngx_http_lua_ngx_timer_helper(L, 0);
     115             : }
     116             : 
     117             : 
     118             : /*
     119             :  * TODO: return a timer handler instead which can be passed to
     120             :  * the ngx.timer.cancel method to cancel the timer.
     121             :  */
     122             : static int
     123           0 : ngx_http_lua_ngx_timer_every(lua_State *L)
     124             : {
     125           0 :     return ngx_http_lua_ngx_timer_helper(L, 1);
     126             : }
     127             : 
     128             : 
     129             : static int
     130           0 : ngx_http_lua_ngx_timer_helper(lua_State *L, int every)
     131             : {
     132             :     int                      nargs, co_ref;
     133             :     u_char                  *p;
     134             :     lua_State               *vm;  /* the main thread */
     135             :     lua_State               *co;
     136             :     ngx_msec_t               delay;
     137           0 :     ngx_event_t             *ev = NULL;
     138             :     ngx_http_request_t      *r;
     139           0 :     ngx_connection_t        *saved_c = NULL;
     140             :     ngx_http_lua_ctx_t      *ctx;
     141             : #if 0
     142             :     ngx_http_connection_t   *hc;
     143             : #endif
     144             : 
     145           0 :     ngx_http_lua_timer_ctx_t      *tctx = NULL;
     146             :     ngx_http_lua_main_conf_t      *lmcf;
     147             : #if 0
     148             :     ngx_http_core_main_conf_t     *cmcf;
     149             : #endif
     150             : 
     151           0 :     nargs = lua_gettop(L);
     152           0 :     if (nargs < 2) {
     153           0 :         return luaL_error(L, "expecting at least 2 arguments but got %d",
     154             :                           nargs);
     155             :     }
     156             : 
     157           0 :     delay = (ngx_msec_t) (luaL_checknumber(L, 1) * 1000);
     158             : 
     159           0 :     if (every && delay == 0) {
     160           0 :         return luaL_error(L, "delay cannot be zero");
     161             :     }
     162             : 
     163           0 :     luaL_argcheck(L, lua_isfunction(L, 2) && !lua_iscfunction(L, 2), 2,
     164             :                   "Lua function expected");
     165             : 
     166           0 :     r = ngx_http_lua_get_req(L);
     167           0 :     if (r == NULL) {
     168           0 :         return luaL_error(L, "no request");
     169             :     }
     170             : 
     171           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     172             : 
     173           0 :     if (ngx_exiting && delay > 0) {
     174           0 :         lua_pushnil(L);
     175           0 :         lua_pushliteral(L, "process exiting");
     176           0 :         return 2;
     177             :     }
     178             : 
     179           0 :     lmcf = ngx_http_get_module_main_conf(r, ngx_http_lua_module);
     180             : 
     181           0 :     if (lmcf->pending_timers >= lmcf->max_pending_timers) {
     182           0 :         lua_pushnil(L);
     183           0 :         lua_pushliteral(L, "too many pending timers");
     184           0 :         return 2;
     185             :     }
     186             : 
     187           0 :     if (lmcf->watcher == NULL) {
     188             :         /* create the watcher fake connection */
     189             : 
     190           0 :         ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
     191             :                        "lua creating fake watcher connection");
     192             : 
     193           0 :         if (ngx_cycle->files) {
     194           0 :             saved_c = ngx_cycle->files[0];
     195             :         }
     196             : 
     197           0 :         lmcf->watcher = ngx_get_connection(0, ngx_cycle->log);
     198             : 
     199           0 :         if (ngx_cycle->files) {
     200           0 :             ngx_cycle->files[0] = saved_c;
     201             :         }
     202             : 
     203           0 :         if (lmcf->watcher == NULL) {
     204           0 :             return luaL_error(L, "no memory");
     205             :         }
     206             : 
     207             :         /* to work around the -1 check in ngx_worker_process_cycle: */
     208           0 :         lmcf->watcher->fd = (ngx_socket_t) -2;
     209             : 
     210           0 :         lmcf->watcher->idle = 1;
     211           0 :         lmcf->watcher->read->handler = ngx_http_lua_abort_pending_timers;
     212           0 :         lmcf->watcher->data = lmcf;
     213             :     }
     214             : 
     215           0 :     vm = ngx_http_lua_get_lua_vm(r, ctx);
     216             : 
     217           0 :     co = lua_newthread(vm);
     218             : 
     219             :     /* L stack: time func [args] */
     220             : 
     221             :     ngx_http_lua_probe_user_coroutine_create(r, L, co);
     222             : 
     223           0 :     lua_createtable(co, 0, 0);  /* the new globals table */
     224             : 
     225             :     /* co stack: global_tb */
     226             : 
     227           0 :     lua_createtable(co, 0, 1);  /* the metatable */
     228           0 :     ngx_http_lua_get_globals_table(co);
     229           0 :     lua_setfield(co, -2, "__index");
     230           0 :     lua_setmetatable(co, -2);
     231             : 
     232             :     /* co stack: global_tb */
     233             : 
     234           0 :     ngx_http_lua_set_globals_table(co);
     235             : 
     236             :     /* co stack: <empty> */
     237             : 
     238             :     dd("stack top: %d", lua_gettop(L));
     239             : 
     240           0 :     lua_xmove(vm, L, 1);    /* move coroutine from main thread to L */
     241             : 
     242             :     /* L stack: time func [args] thread */
     243             :     /* vm stack: empty */
     244             : 
     245           0 :     lua_pushvalue(L, 2);    /* copy entry function to top of L*/
     246             : 
     247             :     /* L stack: time func [args] thread func */
     248             : 
     249           0 :     lua_xmove(L, co, 1);    /* move entry function from L to co */
     250             : 
     251             :     /* L stack: time func [args] thread */
     252             :     /* co stack: func */
     253             : 
     254           0 :     ngx_http_lua_get_globals_table(co);
     255           0 :     lua_setfenv(co, -2);
     256             : 
     257             :     /* co stack: func */
     258             : 
     259           0 :     lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
     260           0 :     lua_rawget(L, LUA_REGISTRYINDEX);
     261             : 
     262             :     /* L stack: time func [args] thread coroutines */
     263             : 
     264           0 :     lua_pushvalue(L, -2);
     265             : 
     266             :     /* L stack: time func [args] thread coroutines thread */
     267             : 
     268           0 :     co_ref = luaL_ref(L, -2);
     269           0 :     lua_pop(L, 1);
     270             : 
     271             :     /* L stack: time func [args] thread */
     272             : 
     273           0 :     if (nargs > 2) {
     274           0 :         lua_pop(L, 1);  /* L stack: time func [args] */
     275           0 :         lua_xmove(L, co, nargs - 2);  /* L stack: time func */
     276             : 
     277             :         /* co stack: func [args] */
     278             :     }
     279             : 
     280           0 :     p = ngx_alloc(sizeof(ngx_event_t) + sizeof(ngx_http_lua_timer_ctx_t),
     281           0 :                   r->connection->log);
     282           0 :     if (p == NULL) {
     283           0 :         goto nomem;
     284             :     }
     285             : 
     286           0 :     ev = (ngx_event_t *) p;
     287             : 
     288           0 :     ngx_memzero(ev, sizeof(ngx_event_t));
     289             : 
     290           0 :     p += sizeof(ngx_event_t);
     291             : 
     292           0 :     tctx = (ngx_http_lua_timer_ctx_t *) p;
     293             : 
     294           0 :     tctx->delay = every ? delay : 0;
     295             : 
     296           0 :     tctx->premature = 0;
     297           0 :     tctx->co_ref = co_ref;
     298           0 :     tctx->co = co;
     299           0 :     tctx->main_conf = r->main_conf;
     300           0 :     tctx->srv_conf = r->srv_conf;
     301           0 :     tctx->loc_conf = r->loc_conf;
     302           0 :     tctx->lmcf = lmcf;
     303             : 
     304           0 :     tctx->pool = ngx_create_pool(128, ngx_cycle->log);
     305           0 :     if (tctx->pool == NULL) {
     306           0 :         goto nomem;
     307             :     }
     308             : 
     309           0 :     if (r->connection) {
     310           0 :         tctx->listening = r->connection->listening;
     311             : 
     312             :     } else {
     313           0 :         tctx->listening = NULL;
     314             :     }
     315             : 
     316           0 :     if (r->connection->addr_text.len) {
     317           0 :         tctx->client_addr_text.data = ngx_palloc(tctx->pool,
     318           0 :                                                  r->connection->addr_text.len);
     319           0 :         if (tctx->client_addr_text.data == NULL) {
     320           0 :             goto nomem;
     321             :         }
     322             : 
     323           0 :         ngx_memcpy(tctx->client_addr_text.data, r->connection->addr_text.data,
     324             :                    r->connection->addr_text.len);
     325           0 :         tctx->client_addr_text.len = r->connection->addr_text.len;
     326             : 
     327             :     } else {
     328           0 :         tctx->client_addr_text.len = 0;
     329           0 :         tctx->client_addr_text.data = NULL;
     330             :     }
     331             : 
     332           0 :     if (ctx && ctx->vm_state) {
     333           0 :         tctx->vm_state = ctx->vm_state;
     334           0 :         tctx->vm_state->count++;
     335             : 
     336             :     } else {
     337           0 :         tctx->vm_state = NULL;
     338             :     }
     339             : 
     340           0 :     ev->handler = ngx_http_lua_timer_handler;
     341           0 :     ev->data = tctx;
     342           0 :     ev->log = ngx_cycle->log;
     343             : 
     344           0 :     lmcf->pending_timers++;
     345             : 
     346           0 :     ngx_add_timer(ev, delay);
     347             : 
     348           0 :     lua_pushinteger(L, 1);
     349           0 :     return 1;
     350             : 
     351           0 : nomem:
     352             : 
     353           0 :     if (tctx && tctx->pool) {
     354           0 :         ngx_destroy_pool(tctx->pool);
     355             :     }
     356             : 
     357           0 :     if (ev) {
     358           0 :         ngx_free(ev);
     359             :     }
     360             : 
     361           0 :     lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
     362           0 :     lua_rawget(L, LUA_REGISTRYINDEX);
     363           0 :     luaL_unref(L, -1, co_ref);
     364             : 
     365           0 :     return luaL_error(L, "no memory");
     366             : }
     367             : 
     368             : 
     369             : static ngx_int_t
     370           0 : ngx_http_lua_timer_copy(ngx_http_lua_timer_ctx_t *old_tctx)
     371             : {
     372             :     int                          nargs, co_ref, i;
     373             :     u_char                      *p;
     374             :     lua_State                   *vm;  /* the main thread */
     375             :     lua_State                   *co;
     376             :     lua_State                   *L;
     377           0 :     ngx_event_t                 *ev = NULL;
     378           0 :     ngx_http_lua_timer_ctx_t    *tctx = NULL;
     379             :     ngx_http_lua_main_conf_t    *lmcf;
     380             : 
     381             :     /* L stack: func [args] */
     382           0 :     L = old_tctx->co;
     383             : 
     384           0 :     lmcf = old_tctx->lmcf;
     385             : 
     386           0 :     vm = old_tctx->vm_state ? old_tctx->vm_state->vm : lmcf->lua;
     387             : 
     388           0 :     co = lua_newthread(vm);
     389             : 
     390           0 :     lua_createtable(co, 0, 0);  /* the new globals table */
     391             : 
     392             :     /* co stack: global_tb */
     393             : 
     394           0 :     lua_createtable(co, 0, 1);  /* the metatable */
     395           0 :     ngx_http_lua_get_globals_table(co);
     396           0 :     lua_setfield(co, -2, "__index");
     397           0 :     lua_setmetatable(co, -2);
     398             : 
     399             :     /* co stack: global_tb */
     400             : 
     401           0 :     ngx_http_lua_set_globals_table(co);
     402             : 
     403             :     /* co stack: <empty> */
     404             : 
     405             :     dd("stack top: %d", lua_gettop(L));
     406             : 
     407           0 :     lua_xmove(vm, L, 1);    /* move coroutine from main thread to L */
     408             : 
     409             :     /* L stack: func [args] thread */
     410             :     /* vm stack: empty */
     411             : 
     412           0 :     lua_pushvalue(L, 1);    /* copy entry function to top of L*/
     413             : 
     414             :     /* L stack: func [args] thread func */
     415             : 
     416           0 :     lua_xmove(L, co, 1);    /* move entry function from L to co */
     417             : 
     418             :     /* L stack: func [args] thread */
     419             :     /* co stack: func */
     420             : 
     421           0 :     ngx_http_lua_get_globals_table(co);
     422           0 :     lua_setfenv(co, -2);
     423             : 
     424             :     /* co stack: func */
     425             : 
     426           0 :     lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
     427           0 :     lua_rawget(L, LUA_REGISTRYINDEX);
     428             : 
     429             :     /* L stack: func [args] thread coroutines */
     430             : 
     431           0 :     lua_pushvalue(L, -2);
     432             : 
     433             :     /* L stack: func [args] thread coroutines thread */
     434             : 
     435           0 :     co_ref = luaL_ref(L, -2);
     436           0 :     lua_pop(L, 2);
     437             : 
     438             :     /* L stack: func [args] */
     439             : 
     440           0 :     nargs = lua_gettop(L);
     441           0 :     if (nargs > 1) {
     442           0 :         for (i = 2; i <= nargs; i++) {
     443           0 :             lua_pushvalue(L, i);
     444             :         }
     445             : 
     446             :         /* L stack: func [args] [args] */
     447             : 
     448           0 :         lua_xmove(L, co, nargs - 1);
     449             : 
     450             :         /* L stack: func [args] */
     451             :         /* co stack: func [args] */
     452             :     }
     453             : 
     454           0 :     p = ngx_alloc(sizeof(ngx_event_t) + sizeof(ngx_http_lua_timer_ctx_t),
     455           0 :                   ngx_cycle->log);
     456           0 :     if (p == NULL) {
     457           0 :         goto nomem;
     458             :     }
     459             : 
     460           0 :     ev = (ngx_event_t *) p;
     461             : 
     462           0 :     ngx_memzero(ev, sizeof(ngx_event_t));
     463             : 
     464           0 :     p += sizeof(ngx_event_t);
     465             : 
     466           0 :     tctx = (ngx_http_lua_timer_ctx_t *) p;
     467             : 
     468           0 :     ngx_memcpy(tctx, old_tctx, sizeof(ngx_http_lua_timer_ctx_t));
     469             : 
     470           0 :     tctx->co_ref = co_ref;
     471           0 :     tctx->co = co;
     472             : 
     473           0 :     tctx->pool = ngx_create_pool(128, ngx_cycle->log);
     474           0 :     if (tctx->pool == NULL) {
     475           0 :         goto nomem;
     476             :     }
     477             : 
     478           0 :     if (tctx->client_addr_text.len) {
     479           0 :         tctx->client_addr_text.data = ngx_palloc(tctx->pool,
     480             :                                                  tctx->client_addr_text.len);
     481           0 :         if (tctx->client_addr_text.data == NULL) {
     482           0 :             goto nomem;
     483             :         }
     484             : 
     485           0 :         ngx_memcpy(tctx->client_addr_text.data, old_tctx->client_addr_text.data,
     486             :                    tctx->client_addr_text.len);
     487             :     }
     488             : 
     489           0 :     if (tctx->vm_state) {
     490           0 :         tctx->vm_state->count++;
     491             :     }
     492             : 
     493           0 :     ev->handler = ngx_http_lua_timer_handler;
     494           0 :     ev->data = tctx;
     495           0 :     ev->log = ngx_cycle->log;
     496             : 
     497           0 :     lmcf->pending_timers++;
     498             : 
     499           0 :     ngx_add_timer(ev, tctx->delay);
     500             : 
     501           0 :     return NGX_OK;
     502             : 
     503           0 : nomem:
     504             : 
     505           0 :     if (tctx && tctx->pool) {
     506           0 :         ngx_destroy_pool(tctx->pool);
     507             :     }
     508             : 
     509           0 :     if (ev) {
     510           0 :         ngx_free(ev);
     511             :     }
     512             : 
     513             :     /* L stack: func [args] */
     514             : 
     515           0 :     lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
     516           0 :     lua_rawget(L, LUA_REGISTRYINDEX);
     517           0 :     luaL_unref(L, -1, co_ref);
     518             : 
     519             :     /* L stack: func [args] coroutines */
     520             : 
     521           0 :     lua_pop(L, 1);
     522             : 
     523           0 :     return NGX_ERROR;
     524             : }
     525             : 
     526             : 
     527             : static void
     528           0 : ngx_http_lua_timer_handler(ngx_event_t *ev)
     529             : {
     530             :     int                      n;
     531             :     lua_State               *L;
     532             :     ngx_int_t                rc;
     533           0 :     ngx_connection_t        *c = NULL;
     534           0 :     ngx_http_request_t      *r = NULL;
     535             :     ngx_http_lua_ctx_t      *ctx;
     536             :     ngx_http_cleanup_t      *cln;
     537             :     ngx_pool_cleanup_t      *pcln;
     538             : 
     539             :     ngx_http_lua_timer_ctx_t         tctx;
     540             :     ngx_http_lua_main_conf_t        *lmcf;
     541             :     ngx_http_core_loc_conf_t        *clcf;
     542             : 
     543           0 :     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
     544             :                    "lua ngx.timer expired");
     545             : 
     546           0 :     ngx_memcpy(&tctx, ev->data, sizeof(ngx_http_lua_timer_ctx_t));
     547           0 :     ngx_free(ev);
     548             : 
     549           0 :     lmcf = tctx.lmcf;
     550             : 
     551           0 :     lmcf->pending_timers--;
     552             : 
     553           0 :     if (!ngx_exiting && tctx.delay > 0) {
     554           0 :         rc = ngx_http_lua_timer_copy(&tctx);
     555           0 :         if (rc != NGX_OK) {
     556           0 :             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
     557             :                           "failed to create the next timer of delay %ud ms",
     558             :                           (unsigned) tctx.delay);
     559             :         }
     560             :     }
     561             : 
     562           0 :     if (lmcf->running_timers >= lmcf->max_running_timers) {
     563           0 :         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
     564             :                       "%i lua_max_running_timers are not enough",
     565             :                       lmcf->max_running_timers);
     566           0 :         goto failed;
     567             :     }
     568             : 
     569           0 :     c = ngx_http_lua_create_fake_connection(tctx.pool);
     570           0 :     if (c == NULL) {
     571           0 :         goto failed;
     572             :     }
     573             : 
     574           0 :     c->log->handler = ngx_http_lua_log_timer_error;
     575           0 :     c->log->data = c;
     576             : 
     577           0 :     c->listening = tctx.listening;
     578           0 :     c->addr_text = tctx.client_addr_text;
     579             : 
     580           0 :     r = ngx_http_lua_create_fake_request(c);
     581           0 :     if (r == NULL) {
     582           0 :         goto failed;
     583             :     }
     584             : 
     585           0 :     r->main_conf = tctx.main_conf;
     586           0 :     r->srv_conf = tctx.srv_conf;
     587           0 :     r->loc_conf = tctx.loc_conf;
     588             : 
     589           0 :     clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
     590             : 
     591             : #if defined(nginx_version) && nginx_version >= 1003014
     592             : 
     593             : #   if nginx_version >= 1009000
     594             : 
     595           0 :     ngx_set_connection_log(r->connection, clcf->error_log);
     596             : 
     597             : #   else
     598             : 
     599             :     ngx_http_set_connection_log(r->connection, clcf->error_log);
     600             : 
     601             : #   endif
     602             : 
     603             : #else
     604             : 
     605             :     c->log->file = clcf->error_log->file;
     606             : 
     607             :     if (!(c->log->log_level & NGX_LOG_DEBUG_CONNECTION)) {
     608             :         c->log->log_level = clcf->error_log->log_level;
     609             :     }
     610             : 
     611             : #endif
     612             : 
     613             :     dd("lmcf: %p", lmcf);
     614             : 
     615           0 :     ctx = ngx_http_lua_create_ctx(r);
     616           0 :     if (ctx == NULL) {
     617           0 :         goto failed;
     618             :     }
     619             : 
     620           0 :     if (tctx.vm_state) {
     621           0 :         ctx->vm_state = tctx.vm_state;
     622             : 
     623           0 :         pcln = ngx_pool_cleanup_add(r->pool, 0);
     624           0 :         if (pcln == NULL) {
     625           0 :             goto failed;
     626             :         }
     627             : 
     628           0 :         pcln->handler = ngx_http_lua_cleanup_vm;
     629           0 :         pcln->data = tctx.vm_state;
     630             :     }
     631             : 
     632           0 :     ctx->cur_co_ctx = &ctx->entry_co_ctx;
     633             : 
     634           0 :     L = ngx_http_lua_get_lua_vm(r, ctx);
     635             : 
     636           0 :     cln = ngx_http_cleanup_add(r, 0);
     637           0 :     if (cln == NULL) {
     638           0 :         goto failed;
     639             :     }
     640             : 
     641           0 :     cln->handler = ngx_http_lua_request_cleanup_handler;
     642           0 :     cln->data = ctx;
     643           0 :     ctx->cleanup = &cln->handler;
     644             : 
     645           0 :     ctx->entered_content_phase = 1;
     646           0 :     ctx->context = NGX_HTTP_LUA_CONTEXT_TIMER;
     647             : 
     648           0 :     r->read_event_handler = ngx_http_block_reading;
     649             : 
     650           0 :     ctx->cur_co_ctx->co_ref = tctx.co_ref;
     651           0 :     ctx->cur_co_ctx->co = tctx.co;
     652           0 :     ctx->cur_co_ctx->co_status = NGX_HTTP_LUA_CO_RUNNING;
     653             : 
     654             :     dd("r connection: %p, log %p", r->connection, r->connection->log);
     655             : 
     656             :     /*  save the request in coroutine globals table */
     657           0 :     ngx_http_lua_set_req(tctx.co, r);
     658             : 
     659           0 :     lmcf->running_timers++;
     660             : 
     661           0 :     lua_pushboolean(tctx.co, tctx.premature);
     662             : 
     663           0 :     n = lua_gettop(tctx.co);
     664           0 :     if (n > 2) {
     665           0 :         lua_insert(tctx.co, 2);
     666             :     }
     667             : 
     668             : #ifdef NGX_LUA_USE_ASSERT
     669           0 :     ctx->cur_co_ctx->co_top = 1;
     670             : #endif
     671             : 
     672           0 :     rc = ngx_http_lua_run_thread(L, r, ctx, n - 1);
     673             : 
     674             :     dd("timer lua run thread: %d", (int) rc);
     675             : 
     676           0 :     if (rc == NGX_ERROR || rc >= NGX_OK) {
     677             :         /* do nothing */
     678             : 
     679           0 :     } else if (rc == NGX_AGAIN) {
     680           0 :         rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 0);
     681             : 
     682           0 :     } else if (rc == NGX_DONE) {
     683           0 :         rc = ngx_http_lua_content_run_posted_threads(L, r, ctx, 1);
     684             : 
     685             :     } else {
     686           0 :         rc = NGX_OK;
     687             :     }
     688             : 
     689           0 :     ngx_http_lua_finalize_request(r, rc);
     690           0 :     return;
     691             : 
     692           0 : failed:
     693             : 
     694           0 :     if (tctx.co_ref && tctx.co) {
     695           0 :         lua_pushlightuserdata(tctx.co, &ngx_http_lua_coroutines_key);
     696           0 :         lua_rawget(tctx.co, LUA_REGISTRYINDEX);
     697           0 :         luaL_unref(tctx.co, -1, tctx.co_ref);
     698           0 :         lua_settop(tctx.co, 0);
     699             :     }
     700             : 
     701           0 :     if (tctx.vm_state) {
     702           0 :         ngx_http_lua_cleanup_vm(tctx.vm_state);
     703             :     }
     704             : 
     705           0 :     if (c) {
     706           0 :         ngx_http_lua_close_fake_connection(c);
     707             : 
     708           0 :     } else if (tctx.pool) {
     709           0 :         ngx_destroy_pool(tctx.pool);
     710             :     }
     711             : }
     712             : 
     713             : 
     714             : static u_char *
     715           0 : ngx_http_lua_log_timer_error(ngx_log_t *log, u_char *buf, size_t len)
     716             : {
     717             :     u_char              *p;
     718             :     ngx_connection_t    *c;
     719             : 
     720           0 :     if (log->action) {
     721           0 :         p = ngx_snprintf(buf, len, " while %s", log->action);
     722           0 :         len -= p - buf;
     723           0 :         buf = p;
     724             :     }
     725             : 
     726           0 :     c = log->data;
     727             : 
     728             :     dd("ctx = %p", c);
     729             : 
     730           0 :     p = ngx_snprintf(buf, len, ", context: ngx.timer");
     731           0 :     len -= p - buf;
     732           0 :     buf = p;
     733             : 
     734           0 :     if (c->addr_text.len) {
     735           0 :         p = ngx_snprintf(buf, len, ", client: %V", &c->addr_text);
     736           0 :         len -= p - buf;
     737           0 :         buf = p;
     738             :     }
     739             : 
     740           0 :     if (c && c->listening && c->listening->addr_text.len) {
     741           0 :         p = ngx_snprintf(buf, len, ", server: %V", &c->listening->addr_text);
     742             :         /* len -= p - buf; */
     743           0 :         buf = p;
     744             :     }
     745             : 
     746           0 :     return buf;
     747             : }
     748             : 
     749             : 
     750             : static void
     751           0 : ngx_http_lua_abort_pending_timers(ngx_event_t *ev)
     752             : {
     753             :     ngx_int_t                    i, n;
     754             :     ngx_event_t                **events;
     755           0 :     ngx_connection_t            *c, *saved_c = NULL;
     756             :     ngx_rbtree_node_t           *cur, *prev, *next, *sentinel, *temp;
     757             :     ngx_http_lua_timer_ctx_t    *tctx;
     758             :     ngx_http_lua_main_conf_t    *lmcf;
     759             : 
     760           0 :     ngx_log_debug0(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
     761             :                    "lua abort pending timers");
     762             : 
     763           0 :     c = ev->data;
     764           0 :     lmcf = c->data;
     765             : 
     766             :     dd("lua connection fd: %d", (int) c->fd);
     767             : 
     768           0 :     if (!c->close) {
     769           0 :         return;
     770             :     }
     771             : 
     772           0 :     c->read->closed = 1;
     773           0 :     c->write->closed = 1;
     774             : 
     775             :     /* we temporarily use a valid fd (0) to make ngx_free_connection happy */
     776             : 
     777           0 :     c->fd = 0;
     778             : 
     779           0 :     if (ngx_cycle->files) {
     780           0 :         saved_c = ngx_cycle->files[0];
     781             :     }
     782             : 
     783           0 :     ngx_free_connection(c);
     784             : 
     785           0 :     c->fd = (ngx_socket_t) -1;
     786             : 
     787           0 :     if (ngx_cycle->files) {
     788           0 :         ngx_cycle->files[0] = saved_c;
     789             :     }
     790             : 
     791           0 :     if (lmcf->pending_timers == 0) {
     792           0 :         return;
     793             :     }
     794             : 
     795             :     /* expire pending timers immediately */
     796             : 
     797           0 :     sentinel = ngx_event_timer_rbtree.sentinel;
     798             : 
     799           0 :     cur = ngx_event_timer_rbtree.root;
     800             : 
     801             :     /* XXX nginx does not guarantee the parent of root is meaningful,
     802             :      * so we temporarily override it to simplify tree traversal. */
     803           0 :     temp = cur->parent;
     804           0 :     cur->parent = NULL;
     805             : 
     806           0 :     prev = NULL;
     807             : 
     808           0 :     events = ngx_pcalloc(ngx_cycle->pool,
     809           0 :                          lmcf->pending_timers * sizeof(ngx_event_t));
     810           0 :     if (events == NULL) {
     811           0 :         return;
     812             :     }
     813             : 
     814           0 :     n = 0;
     815             : 
     816             :     dd("root: %p, root parent: %p, sentinel: %p", cur, cur->parent, sentinel);
     817             : 
     818           0 :     while (n < lmcf->pending_timers) {
     819           0 :         if  (cur == sentinel || cur == NULL) {
     820           0 :             ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
     821             :                           "lua pending timer counter got out of sync: %i",
     822             :                           lmcf->pending_timers);
     823           0 :             break;
     824             :         }
     825             : 
     826             :         dd("prev: %p, cur: %p, cur parent: %p, cur left: %p, cur right: %p",
     827             :            prev, cur, cur->parent, cur->left, cur->right);
     828             : 
     829           0 :         if (prev == cur->parent) {
     830             :             /* neither of the children has been accessed yet */
     831             : 
     832           0 :             next = cur->left;
     833           0 :             if (next == sentinel) {
     834           0 :                 ev = (ngx_event_t *)
     835             :                     ((char *) cur - offsetof(ngx_event_t, timer));
     836             : 
     837           0 :                 if (ev->handler == ngx_http_lua_timer_handler) {
     838             :                     dd("found node: %p", cur);
     839           0 :                     events[n++] = ev;
     840             :                 }
     841             : 
     842           0 :                 next = (cur->right != sentinel) ? cur->right : cur->parent;
     843             :             }
     844             : 
     845           0 :         } else if (prev == cur->left) {
     846             :             /* just accessed the left child */
     847             : 
     848           0 :             ev = (ngx_event_t *)
     849             :                 ((char *) cur - offsetof(ngx_event_t, timer));
     850             : 
     851           0 :             if (ev->handler == ngx_http_lua_timer_handler) {
     852             :                 dd("found node 2: %p", cur);
     853           0 :                 events[n++] = ev;
     854             :             }
     855             : 
     856           0 :             next = (cur->right != sentinel) ? cur->right : cur->parent;
     857             : 
     858           0 :         } else if (prev == cur->right) {
     859             :             /* already accessed both children */
     860           0 :             next = cur->parent;
     861             : 
     862             :         } else {
     863             :             /* not reacheable */
     864           0 :             next = NULL;
     865             :         }
     866             : 
     867           0 :         prev = cur;
     868           0 :         cur = next;
     869             :     }
     870             : 
     871             :     /* restore the old tree root's parent */
     872           0 :     ngx_event_timer_rbtree.root->parent = temp;
     873             : 
     874           0 :     ngx_log_debug1(NGX_LOG_DEBUG_HTTP, ngx_cycle->log, 0,
     875             :                    "lua found %i pending timers to be aborted prematurely",
     876             :                    n);
     877             : 
     878           0 :     for (i = 0; i < n; i++) {
     879           0 :         ev = events[i];
     880             : 
     881           0 :         ngx_rbtree_delete(&ngx_event_timer_rbtree, &ev->timer);
     882             : 
     883             : #if (NGX_DEBUG)
     884           0 :         ev->timer.left = NULL;
     885           0 :         ev->timer.right = NULL;
     886           0 :         ev->timer.parent = NULL;
     887             : #endif
     888             : 
     889           0 :         ev->timer_set = 0;
     890             : 
     891           0 :         ev->timedout = 1;
     892             : 
     893           0 :         tctx = ev->data;
     894           0 :         tctx->premature = 1;
     895             : 
     896             :         dd("calling timer handler prematurely");
     897           0 :         ev->handler(ev);
     898             :     }
     899             : 
     900             : #if 0
     901             :     if (pending_timers) {
     902             :         ngx_log_error(NGX_LOG_ALERT, ngx_cycle->log, 0,
     903             :                       "lua pending timer counter got out of sync: %i",
     904             :                       pending_timers);
     905             :     }
     906             : #endif
     907             : }
     908             : 
     909             : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */

Generated by: LCOV version 1.13