1
0
mirror of https://github.com/Ylianst/MeshAgent synced 2025-12-21 18:53:32 +00:00

Integrated SIGCHLD support with Linux child_process

This commit is contained in:
Bryan Roe
2020-06-01 22:13:00 -07:00
parent 297b5b1a5c
commit 537e4404c6
4 changed files with 136 additions and 24 deletions

View File

@@ -24,6 +24,7 @@ limitations under the License.
#include "ILibDuktape_ReadableStream.h" #include "ILibDuktape_ReadableStream.h"
#include "ILibDuktape_WritableStream.h" #include "ILibDuktape_WritableStream.h"
#include "ILibDuktape_EventEmitter.h" #include "ILibDuktape_EventEmitter.h"
#include "ILibDuktape_ScriptContainer.h"
#define ILibDuktape_ChildProcess_Process "\xFF_ChildProcess_Process" #define ILibDuktape_ChildProcess_Process "\xFF_ChildProcess_Process"
#define ILibDuktape_ChildProcess_MemBuf "\xFF_ChildProcess_MemBuf" #define ILibDuktape_ChildProcess_MemBuf "\xFF_ChildProcess_MemBuf"
@@ -114,6 +115,15 @@ void ILibDuktape_ChildProcess_SubProcess_ExitHandler(ILibProcessPipe_Process sen
p->childProcess = NULL; p->childProcess = NULL;
duk_push_heapptr(p->ctx, p->subProcess); // [childProcess] duk_push_heapptr(p->ctx, p->subProcess); // [childProcess]
#ifdef _POSIX
if (duk_has_prop_string(p->ctx, -1, "_sigsink"))
{
ILibDuktape_EventEmitter_SetupRemoveListener(p->ctx, ILibDuktape_GetProcessObject(p->ctx), "SIGCHLD"); //......][remove][process][SIGCHLD]
duk_get_prop_string(p->ctx, -4, "_sigsink"); // [childProcess][remove][process][SIGCHLD][func]
duk_pcall_method(p->ctx, 2); duk_pop(p->ctx); // [childProcess]
}
#endif
if (Duktape_GetIntPropertyValue(p->ctx, -1, "\xFF_WaitExit", 0) != 0) if (Duktape_GetIntPropertyValue(p->ctx, -1, "\xFF_WaitExit", 0) != 0)
{ {
ILibChain_EndContinue(Duktape_GetChain(p->ctx)); ILibChain_EndContinue(Duktape_GetChain(p->ctx));
@@ -153,11 +163,9 @@ void ILibDuktape_ChildProcess_SubProcess_SendOK(ILibProcessPipe_Process sender,
duk_ret_t ILibDuktape_ChildProcess_Kill(duk_context *ctx) duk_ret_t ILibDuktape_ChildProcess_Kill(duk_context *ctx)
{ {
duk_push_this(ctx); duk_push_this(ctx);
duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_MemBuf); ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_ChildProcess_MemBuf);
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBuffer(ctx, -1, NULL);
ILibProcessPipe_Process_SoftKill(p->childProcess);
if (p != NULL) { ILibProcessPipe_Process_SoftKill(p->childProcess); }
return(0); return(0);
} }
duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx) duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx)
@@ -180,14 +188,14 @@ duk_ret_t ILibDuktape_ChildProcess_waitExit(duk_context *ctx)
duk_push_int(ctx, 1); // [spawnedProcess][flag] duk_push_int(ctx, 1); // [spawnedProcess][flag]
duk_put_prop_string(ctx, -2, "\xFF_WaitExit"); // [spawnedProcess] duk_put_prop_string(ctx, -2, "\xFF_WaitExit"); // [spawnedProcess]
void *mods[] = { ILibGetBaseTimer(Duktape_GetChain(ctx)), Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager) }; void *mods[] = { ILibGetBaseTimer(Duktape_GetChain(ctx)), Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Manager), ILibDuktape_Process_GetSignalListener(ctx) };
#ifdef WIN32 #ifdef WIN32
HANDLE handles[] = { NULL, NULL, NULL, NULL, NULL }; HANDLE handles[] = { NULL, NULL, NULL, NULL, NULL };
ILibProcessPipe_Process p = Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Process); ILibProcessPipe_Process p = Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Process);
ILibProcessPipe_Process_GetWaitHandles(p, &(handles[0]), &(handles[1]), &(handles[2]), &(handles[3])); ILibProcessPipe_Process_GetWaitHandles(p, &(handles[0]), &(handles[1]), &(handles[2]), &(handles[3]));
ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, timeout, (HANDLE**)handles); ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, timeout, (HANDLE**)handles);
#else #else
ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, timeout); ILibChain_Continue(chain, (ILibChain_Link**)mods, 3, timeout);
#endif #endif
return(0); return(0);
@@ -226,6 +234,8 @@ duk_ret_t ILibDuktape_SpawnedProcess_descriptorSetter(duk_context *ctx)
{ {
duk_push_this(ctx); duk_push_this(ctx);
ILibDuktape_ChildProcess_SubProcess *retVal = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_ChildProcess_MemBuf); ILibDuktape_ChildProcess_SubProcess *retVal = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_ChildProcess_MemBuf);
if (retVal != NULL)
{
duk_push_string(ctx, ILibProcessPipe_Process_GetMetadata(retVal->childProcess)); // [string] duk_push_string(ctx, ILibProcessPipe_Process_GetMetadata(retVal->childProcess)); // [string]
duk_get_prop_string(ctx, -1, "split"); // [string][split] duk_get_prop_string(ctx, -1, "split"); // [string][split]
duk_swap_top(ctx, -2); // [split][this] duk_swap_top(ctx, -2); // [split][this]
@@ -237,8 +247,48 @@ duk_ret_t ILibDuktape_SpawnedProcess_descriptorSetter(duk_context *ctx)
duk_push_sprintf(ctx, "%s, %s", duk_get_string(ctx, -1), duk_require_string(ctx, 0)); // [string][newVal] duk_push_sprintf(ctx, "%s, %s", duk_get_string(ctx, -1), duk_require_string(ctx, 0)); // [string][newVal]
ILibProcessPipe_Process_ResetMetadata(retVal->childProcess, (char*)duk_get_string(ctx, -1)); ILibProcessPipe_Process_ResetMetadata(retVal->childProcess, (char*)duk_get_string(ctx, -1));
}
return(0); return(0);
} }
#ifdef _POSIX
extern void ILibProcessPipe_Process_Destroy(void *p);
duk_ret_t ILibDuktape_SpawnedProcess_SIGCHLD_sink(duk_context *ctx)
{
int statusCode = duk_require_int(ctx, 1);
int pid = duk_require_int(ctx, 2);
duk_push_current_function(ctx); // [func]
duk_get_prop_string(ctx, -1, "_child"); // [func][child]
void *child = duk_get_heapptr(ctx, -1);
if (Duktape_GetIntPropertyValue(ctx, -1, "pid", -1) == pid)
{
// This SIGCHLD is for us. Let's unhook from SIGCHLD
ILibDuktape_EventEmitter_SetupRemoveListener(ctx, duk_get_heapptr(ctx, -1), "SIGCHLD"); // [remove][this][SIGCHLD]
duk_push_current_function(ctx); // [remove][this][SIGCHLD][func]
duk_pcall_method(ctx, 2);
// If we got this far, this means the process died without breaking the pipes.
// This will happen if the process was spawned as detached, otherwise this is
// pretty rare, but can happen if you spawn a login shell, then sudo su, then kill the parent.
ILibDuktape_EventEmitter_SetupEmit(ctx, child, "exit"); // [child][emit][this][exit]
duk_push_int(ctx, statusCode); // [child][emit][this][exit][code]
duk_push_null(ctx); // [child][emit][this][exit][code][null]
duk_call_method(ctx, 3); duk_pop(ctx); // ...
duk_push_heapptr(ctx, child); // [child]
void *mProcess = Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Process);
if (mProcess != NULL)
{
duk_del_prop_string(ctx, -1, ILibDuktape_ChildProcess_Process);
duk_del_prop_string(ctx, -1, ILibDuktape_ChildProcess_MemBuf);
ILibProcessPipe_Process_Destroy(mProcess);
}
}
return(0);
}
#endif
ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUSH(duk_context *ctx, ILibProcessPipe_Process mProcess, void *callback) ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUSH(duk_context *ctx, ILibProcessPipe_Process mProcess, void *callback)
{ {
duk_push_object(ctx); // [ChildProcess] duk_push_object(ctx); // [ChildProcess]
@@ -309,6 +359,16 @@ ILibDuktape_ChildProcess_SubProcess* ILibDuktape_ChildProcess_SpawnedProcess_PUS
if (callback != NULL) { ILibDuktape_EventEmitter_AddOnce(emitter, "exit", callback); } if (callback != NULL) { ILibDuktape_EventEmitter_AddOnce(emitter, "exit", callback); }
} }
#ifdef _POSIX
ILibDuktape_EventEmitter_SetupOn(ctx, ILibDuktape_GetProcessObject(ctx), "SIGCHLD"); // [child][on][process][SIGCHLD]
duk_push_c_function(ctx, ILibDuktape_SpawnedProcess_SIGCHLD_sink, DUK_VARARGS); // [child][on][process][SIGCHLD][func]
duk_dup(ctx, -5); // [child][on][process][SIGCHLD][func][child]
duk_put_prop_string(ctx, -2, "_child"); // [child][on][process][SIGCHLD][func]
duk_dup(ctx, -1); // [child][on][process][SIGCHLD][func][func]
duk_put_prop_string(ctx, -6, "_sigsink"); // [child][on][process][SIGCHLD][func]
duk_pcall_method(ctx, 2); duk_pop(ctx); // [child]
#endif
ILibDuktape_CreateEventWithSetterEx(ctx, "descriptorMetadata", ILibDuktape_SpawnedProcess_descriptorSetter); ILibDuktape_CreateEventWithSetterEx(ctx, "descriptorMetadata", ILibDuktape_SpawnedProcess_descriptorSetter);
return(retVal); return(retVal);
} }

View File

@@ -62,6 +62,7 @@ int ILibDuktape_EventEmitter_HasListeners2(ILibDuktape_EventEmitter *emitter, ch
#define ILibDuktape_EventEmitter_SetupEmit(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "emit");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName) #define ILibDuktape_EventEmitter_SetupEmit(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "emit");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName)
#define ILibDuktape_EventEmitter_SetupOn(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "on");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName) #define ILibDuktape_EventEmitter_SetupOn(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "on");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName)
#define ILibDuktape_EventEmitter_SetupPrependOnce(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "prependOnceListener");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName) #define ILibDuktape_EventEmitter_SetupPrependOnce(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "prependOnceListener");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName)
#define ILibDuktape_EventEmitter_SetupRemoveListener(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "removeListener");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName)
#define ILibDuktape_EventEmitter_GetEmitReturn(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "emit_returnValue");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName);if(duk_pcall_method(ctx, 1)!=0){duk_push_null(ctx);} #define ILibDuktape_EventEmitter_GetEmitReturn(ctx, heapptr, eventName) duk_push_heapptr((ctx), heapptr);duk_get_prop_string((ctx), -1, "emit_returnValue");duk_swap_top((ctx), -2);duk_push_string((ctx), eventName);if(duk_pcall_method(ctx, 1)!=0){duk_push_null(ctx);}
int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler

View File

@@ -136,6 +136,41 @@ char exeJavaScriptGuid[] = "B996015880544A19B7F7E9BE44914C18";
}; };
#endif #endif
char *SIGTABLE[] =
{
"INVALID" ,
"SIGHUP" ,
"SIGINT" ,
"SIGQUIT" ,
"SIGILL" ,
"SIGTRAP" ,
"SIGIOT" ,
"SIGBUS" ,
"SIGFPE" ,
"SIGKILL" ,
"SIGUSR1" ,
"SIGSEGV" ,
"SIGUSR2" ,
"SIGPIPE" ,
"SIGALRM" ,
"SIGTERM" ,
"SIGSTKFLT" ,
"SIGCHLD" ,
"SIGCONTv" ,
"SIGSTOP" ,
"SIGTSTP" ,
"SIGTTIN" ,
"SIGTTOU" ,
"SIGURG" ,
"SIGXCPU" ,
"SIGXFSZ" ,
"SIGVTALRM" ,
"SIGPROF" ,
"SIGWINCH" ,
"SIGIO" ,
"SIGPWR"
};
extern void ILibDuktape_MemoryStream_Init(duk_context *ctx); extern void ILibDuktape_MemoryStream_Init(duk_context *ctx);
extern void ILibDuktape_NetworkMonitor_Init(duk_context *ctx); extern void ILibDuktape_NetworkMonitor_Init(duk_context *ctx);
extern int GenerateSHA384FileHash(char *filePath, char *fileHash); extern int GenerateSHA384FileHash(char *filePath, char *fileHash);
@@ -945,6 +980,7 @@ void ILibDuktape_ScriptContainer_Process_SignalListener_PreSelect(void* object,
} }
void ILibDuktape_ScriptContainer_Process_SignalListener_PostSelect(void* object, int slct, fd_set *readset, fd_set *writeset, fd_set *errorset) void ILibDuktape_ScriptContainer_Process_SignalListener_PostSelect(void* object, int slct, fd_set *readset, fd_set *writeset, fd_set *errorset)
{ {
int s;
int bytesRead = 0; int bytesRead = 0;
char sigbuffer[255]; char sigbuffer[255];
ILibChain_Link *link = (ILibChain_Link*)object; ILibChain_Link *link = (ILibChain_Link*)object;
@@ -959,15 +995,20 @@ void ILibDuktape_ScriptContainer_Process_SignalListener_PostSelect(void* object,
switch (((int*)sigbuffer)[1]) switch (((int*)sigbuffer)[1])
{ {
case SIGTERM: case SIGTERM:
ILibDuktape_EventEmitter_SetupEmit(ctx, h, "SIGTERM"); ILibDuktape_EventEmitter_SetupEmit(ctx, h, "SIGTERM"); // [emit][this][SIGTERM]
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "Error Emitting SIGTERM: "); } duk_push_string(ctx, SIGTABLE[((int*)sigbuffer)[1]]); // [emit][this][SIGTERM][name]
if (duk_pcall_method(ctx, 2) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "Error Emitting SIGTERM: "); }
duk_pop(ctx); duk_pop(ctx);
break; break;
case SIGCHLD: case SIGCHLD:
s = 0;
waitpid(((pid_t*)sigbuffer)[2], &s, 0);
ILibDuktape_EventEmitter_SetupEmit(ctx, h, "SIGCHLD"); // [emit][this][SIGCHLD] ILibDuktape_EventEmitter_SetupEmit(ctx, h, "SIGCHLD"); // [emit][this][SIGCHLD]
duk_push_int(ctx, ((pid_t*)sigbuffer)[2]); // [emit][this][SIGCHLD][pid] duk_push_string(ctx, SIGTABLE[((int*)sigbuffer)[1]]); // [emit][this][SIGTERM][name]
duk_push_uint(ctx, ((uid_t*)sigbuffer)[3]); // [emit][this][SIGCHLD][pid][uid] duk_push_int(ctx, s); // [emit][this][SIGCHLD][name][code]
if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "Error Emitting SIGCHLD: "); } duk_push_int(ctx, ((pid_t*)sigbuffer)[2]); // [emit][this][SIGCHLD][name][code][pid]
duk_push_uint(ctx, ((uid_t*)sigbuffer)[3]); // [emit][this][SIGCHLD][name][code][pid][uid]
if (duk_pcall_method(ctx, 5) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "Error Emitting SIGCHLD: "); }
duk_pop(ctx); duk_pop(ctx);
break; break;
default: default:
@@ -1398,7 +1439,15 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
} }
} }
#endif #endif
}
void* ILibDuktape_Process_GetSignalListener(duk_context *ctx)
{
void *ret = NULL;
duk_push_global_object(ctx); // [g]
duk_get_prop_string(ctx, -1, "process"); // [g][p]
ret = Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ScriptContainer_Signal_ListenerPtr);
duk_pop_2(ctx); // ...
return(ret);
} }
void ILibDuktape_ScriptContainer_ExecTimeout_Finalizer(duk_context *ctx, void *timeoutKey) void ILibDuktape_ScriptContainer_ExecTimeout_Finalizer(duk_context *ctx, void *timeoutKey)
{ {

View File

@@ -161,4 +161,6 @@ int ILibDuktape_ScriptContainer_CompileJavaScriptEx(duk_context *ctx, char *payl
#define ILibDuktape_ScriptContainer_CompileJavaScript(ctx, payload, payloadLen) ILibDuktape_ScriptContainer_CompileJavaScriptEx(ctx, payload, payloadLen, NULL, 0) #define ILibDuktape_ScriptContainer_CompileJavaScript(ctx, payload, payloadLen) ILibDuktape_ScriptContainer_CompileJavaScriptEx(ctx, payload, payloadLen, NULL, 0)
int ILibDuktape_ScriptContainer_ExecuteByteCode(duk_context *ctx); int ILibDuktape_ScriptContainer_ExecuteByteCode(duk_context *ctx);
void* ILibDuktape_Process_GetSignalListener(duk_context *ctx);
#endif #endif