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_uthread.c (source / functions) Hit Total Coverage
Test: coverage ngix Lines: 10 119 8.4 %
Date: 2020-03-03 04:25:50 Functions: 1 4 25.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_uthread.h"
      14             : #include "ngx_http_lua_coroutine.h"
      15             : #include "ngx_http_lua_util.h"
      16             : #include "ngx_http_lua_probe.h"
      17             : 
      18             : 
      19             : #if 1
      20             : #undef ngx_http_lua_probe_info
      21             : #define ngx_http_lua_probe_info(msg)
      22             : #endif
      23             : 
      24             : 
      25             : static int ngx_http_lua_uthread_spawn(lua_State *L);
      26             : static int ngx_http_lua_uthread_wait(lua_State *L);
      27             : static int ngx_http_lua_uthread_kill(lua_State *L);
      28             : 
      29             : 
      30             : void
      31          18 : ngx_http_lua_inject_uthread_api(ngx_log_t *log, lua_State *L)
      32             : {
      33             :     /* new thread table */
      34          18 :     lua_createtable(L, 0 /* narr */, 3 /* nrec */);
      35             : 
      36          18 :     lua_pushcfunction(L, ngx_http_lua_uthread_spawn);
      37          18 :     lua_setfield(L, -2, "spawn");
      38             : 
      39          18 :     lua_pushcfunction(L, ngx_http_lua_uthread_wait);
      40          18 :     lua_setfield(L, -2, "wait");
      41             : 
      42          18 :     lua_pushcfunction(L, ngx_http_lua_uthread_kill);
      43          18 :     lua_setfield(L, -2, "kill");
      44             : 
      45          18 :     lua_setfield(L, -2, "thread");
      46          18 : }
      47             : 
      48             : 
      49             : static int
      50           0 : ngx_http_lua_uthread_spawn(lua_State *L)
      51             : {
      52             :     int                           n;
      53             :     ngx_http_request_t           *r;
      54             :     ngx_http_lua_ctx_t           *ctx;
      55           0 :     ngx_http_lua_co_ctx_t        *coctx = NULL;
      56             : 
      57           0 :     n = lua_gettop(L);
      58             : 
      59           0 :     r = ngx_http_lua_get_req(L);
      60           0 :     if (r == NULL) {
      61           0 :         return luaL_error(L, "no request found");
      62             :     }
      63             : 
      64           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
      65           0 :     if (ctx == NULL) {
      66           0 :         return luaL_error(L, "no request ctx found");
      67             :     }
      68             : 
      69           0 :     ngx_http_lua_coroutine_create_helper(L, r, ctx, &coctx);
      70             : 
      71             :     /* anchor the newly created coroutine into the Lua registry */
      72             : 
      73           0 :     lua_pushlightuserdata(L, &ngx_http_lua_coroutines_key);
      74           0 :     lua_rawget(L, LUA_REGISTRYINDEX);
      75           0 :     lua_pushvalue(L, -2);
      76           0 :     coctx->co_ref = luaL_ref(L, -2);
      77           0 :     lua_pop(L, 1);
      78             : 
      79           0 :     if (n > 1) {
      80           0 :         lua_replace(L, 1);
      81           0 :         lua_xmove(L, coctx->co, n - 1);
      82             :     }
      83             : 
      84           0 :     coctx->is_uthread = 1;
      85           0 :     ctx->uthreads++;
      86             : 
      87           0 :     coctx->co_status = NGX_HTTP_LUA_CO_RUNNING;
      88           0 :     ctx->co_op = NGX_HTTP_LUA_USER_THREAD_RESUME;
      89             : 
      90           0 :     ctx->cur_co_ctx->thread_spawn_yielded = 1;
      91             : 
      92           0 :     if (ngx_http_lua_post_thread(r, ctx, ctx->cur_co_ctx) != NGX_OK) {
      93           0 :         return luaL_error(L, "no memory");
      94             :     }
      95             : 
      96           0 :     coctx->parent_co_ctx = ctx->cur_co_ctx;
      97           0 :     ctx->cur_co_ctx = coctx;
      98             : 
      99             :     ngx_http_lua_probe_user_thread_spawn(r, L, coctx->co);
     100             : 
     101             :     dd("yielding with arg %s, top=%d, index-1:%s", luaL_typename(L, -1),
     102             :        (int) lua_gettop(L), luaL_typename(L, 1));
     103           0 :     return lua_yield(L, 1);
     104             : }
     105             : 
     106             : 
     107             : static int
     108           0 : ngx_http_lua_uthread_wait(lua_State *L)
     109             : {
     110             :     int                          i, nargs, nrets;
     111             :     lua_State                   *sub_co;
     112             :     ngx_http_request_t          *r;
     113             :     ngx_http_lua_ctx_t          *ctx;
     114             :     ngx_http_lua_co_ctx_t       *coctx, *sub_coctx;
     115             : 
     116           0 :     r = ngx_http_lua_get_req(L);
     117           0 :     if (r == NULL) {
     118           0 :         return luaL_error(L, "no request found");
     119             :     }
     120             : 
     121           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     122           0 :     if (ctx == NULL) {
     123           0 :         return luaL_error(L, "no request ctx found");
     124             :     }
     125             : 
     126           0 :     ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
     127             :                                | NGX_HTTP_LUA_CONTEXT_ACCESS
     128             :                                | NGX_HTTP_LUA_CONTEXT_CONTENT
     129             :                                | NGX_HTTP_LUA_CONTEXT_TIMER
     130             :                                | NGX_HTTP_LUA_CONTEXT_SSL_CERT);
     131             : 
     132           0 :     coctx = ctx->cur_co_ctx;
     133             : 
     134           0 :     nargs = lua_gettop(L);
     135             : 
     136           0 :     for (i = 1; i <= nargs; i++) {
     137           0 :         sub_co = lua_tothread(L, i);
     138             : 
     139           0 :         luaL_argcheck(L, sub_co, i, "lua thread expected");
     140             : 
     141           0 :         sub_coctx = ngx_http_lua_get_co_ctx(sub_co, ctx);
     142           0 :         if (sub_coctx == NULL) {
     143           0 :             return luaL_error(L, "no co ctx found");
     144             :         }
     145             : 
     146           0 :         if (!sub_coctx->is_uthread) {
     147           0 :             return luaL_error(L, "attempt to wait on a coroutine that is "
     148             :                               "not a user thread");
     149             :         }
     150             : 
     151           0 :         if (sub_coctx->parent_co_ctx != coctx) {
     152           0 :             return luaL_error(L, "only the parent coroutine can wait on the "
     153             :                               "thread");
     154             :         }
     155             : 
     156           0 :         switch (sub_coctx->co_status) {
     157           0 :         case NGX_HTTP_LUA_CO_ZOMBIE:
     158             : 
     159             :             ngx_http_lua_probe_info("found zombie child");
     160             : 
     161           0 :             nrets = lua_gettop(sub_coctx->co);
     162             : 
     163             :             dd("child retval count: %d, %s: %s", (int) nrets,
     164             :                luaL_typename(sub_coctx->co, -1),
     165             :                lua_tostring(sub_coctx->co, -1));
     166             : 
     167           0 :             if (nrets) {
     168           0 :                 lua_xmove(sub_coctx->co, L, nrets);
     169             :             }
     170             : 
     171             : #if 1
     172           0 :             ngx_http_lua_del_thread(r, L, ctx, sub_coctx);
     173           0 :             ctx->uthreads--;
     174             : #endif
     175             : 
     176           0 :             return nrets;
     177             : 
     178           0 :         case NGX_HTTP_LUA_CO_DEAD:
     179             :             dd("uthread already waited: %p (parent %p)", sub_coctx,
     180             :                coctx);
     181             : 
     182           0 :             if (i < nargs) {
     183             :                 /* just ignore it if it is not the last one */
     184           0 :                 continue;
     185             :             }
     186             : 
     187             :             /* being the last one */
     188           0 :             lua_pushnil(L);
     189           0 :             lua_pushliteral(L, "already waited or killed");
     190           0 :             return 2;
     191             : 
     192           0 :         default:
     193             :             dd("uthread %p still alive, status: %d, parent %p", sub_coctx,
     194             :                sub_coctx->co_status, coctx);
     195           0 :             break;
     196             :         }
     197             : 
     198             :         ngx_http_lua_probe_user_thread_wait(L, sub_coctx->co);
     199           0 :         sub_coctx->waited_by_parent = 1;
     200             :     }
     201             : 
     202           0 :     return lua_yield(L, 0);
     203             : }
     204             : 
     205             : 
     206             : static int
     207           0 : ngx_http_lua_uthread_kill(lua_State *L)
     208             : {
     209             :     lua_State                   *sub_co;
     210             :     ngx_http_request_t          *r;
     211             :     ngx_http_lua_ctx_t          *ctx;
     212             :     ngx_http_lua_co_ctx_t       *coctx, *sub_coctx;
     213             : 
     214           0 :     r = ngx_http_lua_get_req(L);
     215           0 :     if (r == NULL) {
     216           0 :         return luaL_error(L, "no request found");
     217             :     }
     218             : 
     219           0 :     ctx = ngx_http_get_module_ctx(r, ngx_http_lua_module);
     220           0 :     if (ctx == NULL) {
     221           0 :         return luaL_error(L, "no request ctx found");
     222             :     }
     223             : 
     224           0 :     ngx_http_lua_check_context(L, ctx, NGX_HTTP_LUA_CONTEXT_REWRITE
     225             :                                | NGX_HTTP_LUA_CONTEXT_ACCESS
     226             :                                | NGX_HTTP_LUA_CONTEXT_CONTENT
     227             :                                | NGX_HTTP_LUA_CONTEXT_TIMER
     228             :                                | NGX_HTTP_LUA_CONTEXT_SSL_CERT);
     229             : 
     230           0 :     coctx = ctx->cur_co_ctx;
     231             : 
     232           0 :     sub_co = lua_tothread(L, 1);
     233           0 :     luaL_argcheck(L, sub_co, 1, "lua thread expected");
     234             : 
     235           0 :     sub_coctx = ngx_http_lua_get_co_ctx(sub_co, ctx);
     236             : 
     237           0 :     if (sub_coctx == NULL) {
     238           0 :         return luaL_error(L, "no co ctx found");
     239             :     }
     240             : 
     241           0 :     if (!sub_coctx->is_uthread) {
     242           0 :         lua_pushnil(L);
     243           0 :         lua_pushliteral(L, "not user thread");
     244           0 :         return 2;
     245             :     }
     246             : 
     247           0 :     if (sub_coctx->parent_co_ctx != coctx) {
     248           0 :         lua_pushnil(L);
     249           0 :         lua_pushliteral(L, "killer not parent");
     250           0 :         return 2;
     251             :     }
     252             : 
     253           0 :     if (sub_coctx->pending_subreqs > 0) {
     254           0 :         lua_pushnil(L);
     255           0 :         lua_pushliteral(L, "pending subrequests");
     256           0 :         return 2;
     257             :     }
     258             : 
     259           0 :     switch (sub_coctx->co_status) {
     260           0 :     case NGX_HTTP_LUA_CO_ZOMBIE:
     261           0 :         ngx_http_lua_del_thread(r, L, ctx, sub_coctx);
     262           0 :         ctx->uthreads--;
     263             : 
     264           0 :         lua_pushnil(L);
     265           0 :         lua_pushliteral(L, "already terminated");
     266           0 :         return 2;
     267             : 
     268           0 :     case NGX_HTTP_LUA_CO_DEAD:
     269           0 :         lua_pushnil(L);
     270           0 :         lua_pushliteral(L, "already waited or killed");
     271           0 :         return 2;
     272             : 
     273           0 :     default:
     274           0 :         ngx_http_lua_cleanup_pending_operation(sub_coctx);
     275           0 :         ngx_http_lua_del_thread(r, L, ctx, sub_coctx);
     276           0 :         ctx->uthreads--;
     277             : 
     278           0 :         lua_pushinteger(L, 1);
     279           0 :         return 1;
     280             :     }
     281             : 
     282             :     /* not reacheable */
     283             : }
     284             : 
     285             : /* vi:set ft=c ts=4 sw=4 et fdm=marker: */

Generated by: LCOV version 1.13