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:
@@ -24,6 +24,7 @@ limitations under the License.
|
||||
#include "ILibDuktape_ReadableStream.h"
|
||||
#include "ILibDuktape_WritableStream.h"
|
||||
#include "ILibDuktape_EventEmitter.h"
|
||||
#include "ILibDuktape_ScriptContainer.h"
|
||||
|
||||
#define ILibDuktape_ChildProcess_Process "\xFF_ChildProcess_Process"
|
||||
#define ILibDuktape_ChildProcess_MemBuf "\xFF_ChildProcess_MemBuf"
|
||||
@@ -114,6 +115,15 @@ void ILibDuktape_ChildProcess_SubProcess_ExitHandler(ILibProcessPipe_Process sen
|
||||
p->childProcess = NULL;
|
||||
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)
|
||||
{
|
||||
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_push_this(ctx);
|
||||
duk_get_prop_string(ctx, -1, ILibDuktape_ChildProcess_MemBuf);
|
||||
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBuffer(ctx, -1, NULL);
|
||||
|
||||
ILibProcessPipe_Process_SoftKill(p->childProcess);
|
||||
ILibDuktape_ChildProcess_SubProcess *p = (ILibDuktape_ChildProcess_SubProcess*)Duktape_GetBufferProperty(ctx, -1, ILibDuktape_ChildProcess_MemBuf);
|
||||
|
||||
if (p != NULL) { ILibProcessPipe_Process_SoftKill(p->childProcess); }
|
||||
return(0);
|
||||
}
|
||||
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_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
|
||||
HANDLE handles[] = { NULL, NULL, NULL, NULL, NULL };
|
||||
ILibProcessPipe_Process p = Duktape_GetPointerProperty(ctx, -1, ILibDuktape_ChildProcess_Process);
|
||||
ILibProcessPipe_Process_GetWaitHandles(p, &(handles[0]), &(handles[1]), &(handles[2]), &(handles[3]));
|
||||
ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, timeout, (HANDLE**)handles);
|
||||
#else
|
||||
ILibChain_Continue(chain, (ILibChain_Link**)mods, 2, timeout);
|
||||
ILibChain_Continue(chain, (ILibChain_Link**)mods, 3, timeout);
|
||||
#endif
|
||||
|
||||
return(0);
|
||||
@@ -226,6 +234,8 @@ duk_ret_t ILibDuktape_SpawnedProcess_descriptorSetter(duk_context *ctx)
|
||||
{
|
||||
duk_push_this(ctx);
|
||||
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_get_prop_string(ctx, -1, "split"); // [string][split]
|
||||
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]
|
||||
|
||||
ILibProcessPipe_Process_ResetMetadata(retVal->childProcess, (char*)duk_get_string(ctx, -1));
|
||||
}
|
||||
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)
|
||||
{
|
||||
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); }
|
||||
}
|
||||
|
||||
#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);
|
||||
return(retVal);
|
||||
}
|
||||
|
||||
@@ -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_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_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);}
|
||||
|
||||
int ILibDuktape_EventEmitter_AddOn(ILibDuktape_EventEmitter *emitter, char *eventName, void *heapptr); // Add native event handler
|
||||
|
||||
@@ -136,6 +136,41 @@ char exeJavaScriptGuid[] = "B996015880544A19B7F7E9BE44914C18";
|
||||
};
|
||||
#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_NetworkMonitor_Init(duk_context *ctx);
|
||||
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)
|
||||
{
|
||||
int s;
|
||||
int bytesRead = 0;
|
||||
char sigbuffer[255];
|
||||
ILibChain_Link *link = (ILibChain_Link*)object;
|
||||
@@ -959,15 +995,20 @@ void ILibDuktape_ScriptContainer_Process_SignalListener_PostSelect(void* object,
|
||||
switch (((int*)sigbuffer)[1])
|
||||
{
|
||||
case SIGTERM:
|
||||
ILibDuktape_EventEmitter_SetupEmit(ctx, h, "SIGTERM");
|
||||
if (duk_pcall_method(ctx, 1) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "Error Emitting SIGTERM: "); }
|
||||
ILibDuktape_EventEmitter_SetupEmit(ctx, h, "SIGTERM"); // [emit][this][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);
|
||||
break;
|
||||
case SIGCHLD:
|
||||
s = 0;
|
||||
waitpid(((pid_t*)sigbuffer)[2], &s, 0);
|
||||
ILibDuktape_EventEmitter_SetupEmit(ctx, h, "SIGCHLD"); // [emit][this][SIGCHLD]
|
||||
duk_push_int(ctx, ((pid_t*)sigbuffer)[2]); // [emit][this][SIGCHLD][pid]
|
||||
duk_push_uint(ctx, ((uid_t*)sigbuffer)[3]); // [emit][this][SIGCHLD][pid][uid]
|
||||
if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "Error Emitting SIGCHLD: "); }
|
||||
duk_push_string(ctx, SIGTABLE[((int*)sigbuffer)[1]]); // [emit][this][SIGTERM][name]
|
||||
duk_push_int(ctx, s); // [emit][this][SIGCHLD][name][code]
|
||||
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);
|
||||
break;
|
||||
default:
|
||||
@@ -1398,7 +1439,15 @@ void ILibDuktape_ScriptContainer_Process_Init(duk_context *ctx, char **argList)
|
||||
}
|
||||
}
|
||||
#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)
|
||||
{
|
||||
|
||||
@@ -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)
|
||||
int ILibDuktape_ScriptContainer_ExecuteByteCode(duk_context *ctx);
|
||||
|
||||
void* ILibDuktape_Process_GetSignalListener(duk_context *ctx);
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user