@@ -827,6 +827,47 @@ globalHookHandler(TSCont contp, TSEvent event ATS_UNUSED, void *edata)
827827 return 0 ;
828828}
829829
830+ static int
831+ shutdownHookHandler (TSCont contp, TSEvent /* event ATS_UNUSED */ , void * /* edata ATS_UNUSED */ )
832+ {
833+ ts_lua_instance_conf *const conf = (ts_lua_instance_conf *)TSContDataGet (contp);
834+
835+ for (int index = 0 ; index < conf->states ; ++index) {
836+ ts_lua_main_ctx *const main_ctx = &ts_lua_g_main_ctx_array[index];
837+
838+ TSMutexLock (main_ctx->mutexp );
839+
840+ lua_State *const L = main_ctx->lua ;
841+
842+ // Restore the conf-specific global table so lua_getglobal resolves
843+ // functions from the loaded script, matching ts_lua_reload_module.
844+ lua_pushlightuserdata (L, conf);
845+ lua_rawget (L, LUA_REGISTRYINDEX);
846+ lua_replace (L, LUA_GLOBALSINDEX);
847+
848+ lua_getglobal (L, TS_LUA_FUNCTION_G_SHUT_DOWN);
849+
850+ if (lua_type (L, -1 ) == LUA_TFUNCTION) {
851+ if (lua_pcall (L, 0 , 0 , 0 ) != 0 ) {
852+ TSError (" [ts_lua][%s] lua_pcall failed for script '%s' state %d: %s" , __FUNCTION__, conf->script , index,
853+ lua_tostring (L, -1 ));
854+ lua_pop (L, 1 );
855+ }
856+ } else {
857+ lua_pop (L, 1 );
858+ }
859+
860+ // Restore LUA_GLOBALSINDEX to an empty table, matching the resting state
861+ // established by ts_lua_add_module and ts_lua_reload_module.
862+ lua_newtable (L);
863+ lua_replace (L, LUA_GLOBALSINDEX);
864+
865+ TSMutexUnlock (main_ctx->mutexp );
866+ }
867+
868+ return 0 ;
869+ }
870+
830871void
831872TSPluginInit (int argc, const char *argv[])
832873{
@@ -1046,7 +1087,7 @@ TSPluginInit(int argc, const char *argv[])
10461087 }
10471088 TSContDataSet (vconn_contp, conf);
10481089
1049- // adding hook based on whther the lua global vconn function exists
1090+ // adding hook based on whether the lua global vconn function exists
10501091 ts_lua_vconn_ctx *vconn_ctx = ts_lua_create_vconn_ctx (main_ctx, conf);
10511092 lua_State *vl = vconn_ctx->lua ;
10521093
@@ -1059,6 +1100,30 @@ TSPluginInit(int argc, const char *argv[])
10591100
10601101 ts_lua_destroy_vconn_ctx (vconn_ctx);
10611102
1103+ // adding shutdown hook if the lua global shutdown function exists
1104+ ts_lua_main_ctx *shutdown_main_ctx = &ts_lua_g_main_ctx_array[0 ];
1105+ ts_lua_http_ctx *shutdown_http_ctx = ts_lua_create_http_ctx (shutdown_main_ctx, conf);
1106+ lua_State *sl = shutdown_http_ctx->cinfo .routine .lua ;
1107+
1108+ lua_getglobal (sl, TS_LUA_FUNCTION_G_SHUT_DOWN);
1109+ if (lua_type (sl, -1 ) == LUA_TFUNCTION) {
1110+ TSMutex shutdown_mutex = TSMutexCreate ();
1111+ TSCont shutdown_contp = TSContCreate (shutdownHookHandler, shutdown_mutex);
1112+ if (!shutdown_contp) {
1113+ TSError (" [ts_lua][%s] could not create shutdown continuation" , __FUNCTION__);
1114+ if (shutdown_mutex) {
1115+ TSMutexDestroy (shutdown_mutex);
1116+ }
1117+ } else {
1118+ TSContDataSet (shutdown_contp, conf);
1119+ TSLifecycleHookAdd (TS_LIFECYCLE_SHUTDOWN_HOOK, shutdown_contp);
1120+ Dbg (dbg_ctl, " shutdown_hook added" );
1121+ }
1122+ }
1123+ lua_pop (sl, 1 );
1124+
1125+ ts_lua_destroy_http_ctx (shutdown_http_ctx);
1126+
10621127 // support for reload as global plugin
10631128 if (reload) {
10641129 TSCont config_contp = TSContCreate (configHandler, nullptr );
0 commit comments