diff --git a/microscript/ILibDuktape_Polyfills.c b/microscript/ILibDuktape_Polyfills.c index c7225cd..e33343d 100644 --- a/microscript/ILibDuktape_Polyfills.c +++ b/microscript/ILibDuktape_Polyfills.c @@ -42,6 +42,7 @@ limitations under the License. #define ILibDuktape_DescriptorEvents_FD "\xFF_DescriptorEvents_FD" #define ILibDuktape_DescriptorEvents_Options "\xFF_DescriptorEvents_Options" #define ILibDuktape_DescriptorEvents_WaitHandle "\xFF_DescriptorEvents_WindowsWaitHandle" +#define ILibDuktape_ChainViewer_PromiseList "\xFF_ChainViewer_PromiseList" #define CP_ISO8859_1 28591 typedef enum ILibDuktape_Console_DestinationFlags @@ -2252,17 +2253,54 @@ void ILibDuktape_ChainViewer_PostSelect(void* object, int slct, fd_set *readset, { duk_context *ctx = (duk_context*)((void**)((ILibTransport*)object)->ChainLink.ExtraMemoryPtr)[0]; void *hptr = ((void**)((ILibTransport*)object)->ChainLink.ExtraMemoryPtr)[1]; - - ILibDuktape_EventEmitter_SetupEmit(ctx, hptr, "PostSelect"); // [emit][this][name] - duk_push_int(ctx, slct); // [emit][this][name][select] + int top = duk_get_top(ctx); + char *m; + duk_push_heapptr(ctx, hptr); // [this] + if (ILibDuktape_EventEmitter_HasListenersEx(ctx, -1, "PostSelect")) + { + ILibDuktape_EventEmitter_SetupEmit(ctx, hptr, "PostSelect"); // [this][emit][this][name] + duk_push_int(ctx, slct); // [this][emit][this][name][select] + m = ILibChain_GetMetaDataFromDescriptorSet(Duktape_GetChain(ctx), readset, writeset, errorset); + duk_push_string(ctx, m); // [this][emit][this][name][select][string] + if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ChainViewer.emit('PostSelect'): Error "); } + duk_pop(ctx); // [this] + } - char *m = ILibChain_GetMetaDataFromDescriptorSet(Duktape_GetChain(ctx), readset, writeset, errorset); - duk_push_string(ctx, m); - if (duk_pcall_method(ctx, 3) != 0) { ILibDuktape_Process_UncaughtExceptionEx(ctx, "ChainViewer.emit('PostSelect'): Error "); } - duk_pop(ctx); + duk_get_prop_string(ctx, -1, ILibDuktape_ChainViewer_PromiseList); // [this][list] + while (duk_get_length(ctx, -1) > 0) + { + m = ILibChain_GetMetaDataFromDescriptorSetEx(duk_ctx_chain(ctx), readset, writeset, errorset); + duk_array_shift(ctx, -1); // [this][list][promise] + duk_get_prop_string(ctx, -1, "_RES"); // [this][list][promise][RES] + duk_swap_top(ctx, -2); // [this][list][RES][this] + duk_push_string(ctx, m); // [this][list][RES][this][str] + duk_pcall_method(ctx, 1); duk_pop(ctx); // [this][list] + } + + duk_set_top(ctx, top); } extern void ILibPrependToChain(void *Chain, void *object); + +duk_ret_t ILibDuktape_ChainViewer_getSnapshot_promise(duk_context *ctx) +{ + duk_push_this(ctx); // [promise] + duk_dup(ctx, 0); duk_put_prop_string(ctx, -2, "_RES"); + duk_dup(ctx, 1); duk_put_prop_string(ctx, -2, "_REJ"); + return(0); +} +duk_ret_t ILibDuktape_ChainViewer_getSnapshot(duk_context *ctx) +{ + duk_push_this(ctx); // [viewer] + duk_get_prop_string(ctx, -1, ILibDuktape_ChainViewer_PromiseList); // [viewer][list] + duk_eval_string(ctx, "require('promise')"); // [viewer][list][promise] + duk_push_c_function(ctx, ILibDuktape_ChainViewer_getSnapshot_promise, 2); // [viewer][list][promise][func] + duk_new(ctx, 1); // [viewer][list][promise] + duk_dup(ctx, -1); // [viewer][list][promise][promise] + duk_put_prop_index(ctx, -3, (duk_uarridx_t)duk_get_length(ctx, -3)); // [viewer][list][promise] + ILibForceUnBlockChain(duk_ctx_chain(ctx)); + return(1); +} void ILibDuktape_ChainViewer_Push(duk_context *ctx, void *chain) { duk_push_object(ctx); // [viewer] @@ -2274,6 +2312,8 @@ void ILibDuktape_ChainViewer_Push(duk_context *ctx, void *chain) ((void**)t->ChainLink.ExtraMemoryPtr)[1] = duk_get_heapptr(ctx, -1); ILibDuktape_EventEmitter *emitter = ILibDuktape_EventEmitter_Create(ctx); ILibDuktape_EventEmitter_CreateEventEx(emitter, "PostSelect"); + ILibDuktape_CreateInstanceMethod(ctx, "getSnapshot", ILibDuktape_ChainViewer_getSnapshot, 0); + duk_push_array(ctx); duk_put_prop_string(ctx, -2, ILibDuktape_ChainViewer_PromiseList); ILibPrependToChain(chain, (void*)t); } diff --git a/microscript/ILibDuktape_net.c b/microscript/ILibDuktape_net.c index a8b3656..f1677d3 100644 --- a/microscript/ILibDuktape_net.c +++ b/microscript/ILibDuktape_net.c @@ -871,7 +871,7 @@ BOOL ILibDuktape_server_ipc_ReadSink(void *chain, HANDLE h, ILibWaitHandle_Error ILibMemory_ReallocateRaw(&(winIPC->buffer), winIPC->bufferLength == 0 ? ILibDuktape_net_IPC_BUFFERSIZE : winIPC->bufferLength * 2); winIPC->bufferLength = winIPC->bufferLength == 0 ? ILibDuktape_net_IPC_BUFFERSIZE : winIPC->bufferLength * 2; } - ILibChain_ReadEx(chain, h, &(winIPC->read_overlapped), winIPC->buffer + winIPC->bufferOffset + winIPC->totalRead, winIPC->bufferLength - winIPC->totalRead, ILibDuktape_server_ipc_ReadSink, winIPC); + ILibChain_ReadEx2(chain, h, &(winIPC->read_overlapped), winIPC->buffer + winIPC->bufferOffset + winIPC->totalRead, winIPC->bufferLength - winIPC->totalRead, ILibDuktape_server_ipc_ReadSink, winIPC, "server_ipc_ReadSink()"); return(TRUE); } else @@ -882,6 +882,7 @@ BOOL ILibDuktape_server_ipc_ReadSink(void *chain, HANDLE h, ILibWaitHandle_Error else { // I/O Errors + if (winIPC->mServer != NULL) { winIPC->clientConnected = 0; } ILibDuktape_DuplexStream_Closed(winIPC->ds); return(FALSE); } @@ -909,7 +910,7 @@ BOOL ILibDuktape_server_ipc_WriteSink(void *chain, HANDLE h, ILibWaitHandle_Erro if (duk_get_length(winIPC->ctx, -1) == 0) { break; } duk_get_prop_index(winIPC->ctx, -1, 0); // [obj][array][buffer] buf = Duktape_GetBuffer(winIPC->ctx, -1, &bufLen); - d = ILibChain_WriteEx(chain, h, &(winIPC->write_overlapped), buf, (int)bufLen, ILibDuktape_server_ipc_WriteSink, winIPC); + d = ILibChain_WriteEx2(chain, h, &(winIPC->write_overlapped), buf, (int)bufLen, ILibDuktape_server_ipc_WriteSink, winIPC, "server_ipc_WriteSink()"); duk_pop(winIPC->ctx); // [obj][array] } @@ -972,7 +973,7 @@ ILibTransport_DoneState ILibDuktape_net_server_IPC_WriteSink(ILibDuktape_DuplexS if (len == 0) { // No Pending Writes - ILibTransport_DoneState ret = ILibChain_WriteEx(winIPC->mChain, winIPC->mPipeHandle, &(winIPC->write_overlapped), q, bufferLen, ILibDuktape_server_ipc_WriteSink, winIPC); + ILibTransport_DoneState ret = ILibChain_WriteEx2(winIPC->mChain, winIPC->mPipeHandle, &(winIPC->write_overlapped), q, bufferLen, ILibDuktape_server_ipc_WriteSink, winIPC, "net_server_IPC_WriteSink()"); if (ret != ILibTransport_DoneState_INCOMPLETE) { duk_push_heapptr(winIPC->ctx, winIPC->mSocket); // [obj] @@ -989,6 +990,7 @@ void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void * { if (!ILibMemory_CanaryOK(user)) { return; } ILibDuktape_net_WindowsIPC *winIPC = (ILibDuktape_net_WindowsIPC*)user; + if (winIPC->mServer != NULL && winIPC->mPipeHandle == NULL) { return; } // Already Closed if (winIPC->mPipeHandle != NULL) { @@ -1004,11 +1006,15 @@ void ILibDuktape_net_server_IPC_EndSink(ILibDuktape_DuplexStream *stream, void * duk_context *ctx = winIPC->ctx; // We need to dereference this, because winIPC will go out of scope when we call listen CloseHandle(winIPC->overlapped.hEvent); winIPC->overlapped.hEvent = NULL; - duk_push_heapptr(ctx, winIPC->mServer); // [server] - duk_get_prop_string(ctx, -1, "listen"); // [server][listen] - duk_swap_top(ctx, -2); // [listen][this] - duk_get_prop_string(ctx, -1, ILibDuktape_SERVER2LISTENOPTIONS); // [listen][this][options] - duk_pcall_method(ctx, 1); duk_pop(ctx); // ... + duk_push_heapptr(ctx, winIPC->mServer); // [server] + if (Duktape_GetBooleanProperty(ctx, -1, ILibDuktape_net_server_closed_needEmit, 0) == 0) + { + duk_get_prop_string(ctx, -1, "listen"); // [server][listen] + duk_swap_top(ctx, -2); // [listen][this] + duk_get_prop_string(ctx, -1, ILibDuktape_SERVER2LISTENOPTIONS); // [listen][this][options] + duk_pcall_method(ctx, 1); // [ret] + } + duk_pop(ctx); // ... } } duk_ret_t ILibDuktape_net_server_IPC_ConnectSink_Finalizer(duk_context *ctx) @@ -1219,7 +1225,7 @@ duk_ret_t ILibDuktape_net_server_listen(duk_context *ctx) } //printf("ConnectNamedPipe(%s)\n", ipc); ConnectNamedPipe(winIPC->mPipeHandle, &winIPC->overlapped); - ILibChain_AddWaitHandle(duk_ctx_chain(ctx), winIPC->overlapped.hEvent, -1, ILibDuktape_net_server_IPC_ConnectSink, winIPC); + ILibChain_AddWaitHandleEx(duk_ctx_chain(ctx), winIPC->overlapped.hEvent, -1, ILibDuktape_net_server_IPC_ConnectSink, winIPC, "net_server_listen()"); if (pIPC_SA != NULL) { LocalFree(IPC_ACL); } return(1); diff --git a/microstack/ILibParsers.c b/microstack/ILibParsers.c index b73da0f..dbbe26c 100644 --- a/microstack/ILibParsers.c +++ b/microstack/ILibParsers.c @@ -927,6 +927,7 @@ typedef struct ILibChain_WaitHandleInfo void *node; ILibChain_WaitHandleHandler handler; void *user; + char *metadata; struct timeval expiration; }ILibChain_WaitHandleInfo; #endif @@ -2991,6 +2992,85 @@ char *ILibChain_GetMetaDataFromDescriptorSet(void *chain, fd_set *inr, fd_set *i } return(ret); } +char *ILibChain_GetMetaDataFromDescriptorSetEx(void *chain, fd_set *inr, fd_set *inw, fd_set *ine) +{ + ILibBaseChain *bchain = (ILibBaseChain*)chain; + char *retStr = (char*)ILibMemory_SmartAllocate(65535); + int len = 0; + void *node = ILibLinkedList_GetNode_Head(((ILibBaseChain*)chain)->Links); + ILibChain_Link *module; + fd_set readset; + fd_set errorset; + fd_set writeset; + fd_set emptyset; FD_ZERO(&emptyset); + struct timeval tv; tv.tv_sec = 0; tv.tv_usec = 0; + int selectTimeout = UPNP_MAX_WAIT * 1000; + int f; + while (node != NULL && (module = (ILibChain_Link*)ILibLinkedList_GetDataFromNode(node)) != NULL) + { + if (module->PreSelectHandler != NULL) + { + FD_ZERO(&readset); + FD_ZERO(&errorset); + FD_ZERO(&writeset); + + module->PreSelectHandler(module, &readset, &writeset, &errorset, &selectTimeout); + if (memcmp(&readset, &emptyset, sizeof(fd_set)) != 0 || memcmp(&writeset, &emptyset, sizeof(fd_set)) != 0 || memcmp(&errorset, &emptyset, sizeof(fd_set)) != 0) + { + // Descriptors were added +#ifdef WIN32 + SOCKET slist[FD_SETSIZE]; + int scount = 0; + for (f = 0; f < readset.fd_count; ++f) + { + slist[scount++] = readset.fd_array[f]; + } + for (f = 0; f < writeset.fd_count; ++f) + { + if (FD_ISSET(writeset.fd_array[f], &readset) == 0) + { + slist[scount++] = writeset.fd_array[f]; + } + } + for (f = 0; f < errorset.fd_count; ++f) + { + if (FD_ISSET(errorset.fd_array[f], &readset) == 0 && FD_ISSET(errorset.fd_array[f], &writeset) == 0) + { + slist[scount++] = errorset.fd_array[f]; + } + } + for (f = 0; f < scount; ++f) + { + len += sprintf_s(retStr + len, ILibMemory_Size(retStr) - len, " FD[%d] (R: %d, W: %d, E: %d) => %s\n", (int)slist[f], FD_ISSET(slist[f], inr), FD_ISSET(slist[f], inw), FD_ISSET(slist[f], ine), ((ILibChain_Link*)module)->MetaData); + } + +#else + for (f = 0; f < FD_SETSIZE; ++f) + { + if (FD_ISSET(f, &readset) || FD_ISSET(f, &writeset) || FD_ISSET(f, &errorset)) + { + len += sprintf_s(retStr + len, ILibMemory_Size(retStr) - len, " FD[%d] (R: %d, W: %d, E: %d) => %s\n", f, FD_ISSET(f, inr), FD_ISSET(f, inw), FD_ISSET(f, ine), ((ILibChain_Link*)module)->MetaData); + } + } +#endif + } + } + node = ILibLinkedList_GetNextNode(node); + } + +#ifdef WIN32 + for (f = 0; f < FD_SETSIZE && f < bchain->lastDescriptorCount; ++f) + { + if (bchain->WaitHandles[f] != NULL && bchain->WaitHandles[ILibChain_HandleInfoIndex(f)] != NULL) + { + len += sprintf_s(retStr + len, ILibMemory_Size(retStr) - len, " H[%p] (Signaled: %d) => %s\n", bchain->WaitHandles[f], WaitForSingleObjectEx(bchain->WaitHandles[f], 0, FALSE) == 0, ((ILibChain_WaitHandleInfo*)bchain->WaitHandles[ILibChain_HandleInfoIndex(f)])->metadata); + } + } +#endif + + retStr[len] = 0; + return(retStr); +} void *ILibChain_GetObjectForDescriptor(void *chain, int fd) { @@ -3050,7 +3130,7 @@ BOOL ILibChain_WriteEx_Sink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus st { // More Data to write BOOL ret = FALSE; - switch (ILibChain_WriteEx(chain, h, data->p, data->buffer, data->bytesLeft, ILibChain_WriteEx_Sink2, data)) + switch (ILibChain_WriteEx2(chain, h, data->p, data->buffer, data->bytesLeft, ILibChain_WriteEx_Sink2, data, data->metadata)) { case ILibTransport_DoneState_COMPLETE: data->totalWritten += data->bytesLeft; @@ -3115,7 +3195,7 @@ BOOL ILibChain_ReadEx_Sink(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus sta } } } -ILibTransport_DoneState ILibChain_WriteEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_WriteEx_Handler handler, void *user) +ILibTransport_DoneState ILibChain_WriteEx2(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_WriteEx_Handler handler, void *user, char *metadata) { int e = 0; if (!WriteFile(h, buffer, (DWORD)bufferLen, NULL, p)) @@ -3131,7 +3211,8 @@ ILibTransport_DoneState ILibChain_WriteEx(void *chain, HANDLE h, OVERLAPPED *p, state->handler = handler; state->fileHandle = h; state->user = user; - ILibChain_AddWaitHandle(chain, p->hEvent, -1, ILibChain_WriteEx_Sink, state); + state->metadata = metadata; + ILibChain_AddWaitHandleEx(chain, p->hEvent, -1, ILibChain_WriteEx_Sink, state, metadata); return(ILibTransport_DoneState_INCOMPLETE); } else @@ -3146,7 +3227,7 @@ ILibTransport_DoneState ILibChain_WriteEx(void *chain, HANDLE h, OVERLAPPED *p, return(ILibTransport_DoneState_COMPLETE); } } -void ILibChain_ReadEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_ReadEx_Handler handler, void *user) +void ILibChain_ReadEx2(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_ReadEx_Handler handler, void *user, char *metadata) { DWORD bytesRead = 0; int e = 0; @@ -3160,7 +3241,7 @@ void ILibChain_ReadEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bu state->handler = handler; state->fileHandle = h; state->user = user; - ILibChain_AddWaitHandle(chain, p->hEvent, -1, ILibChain_ReadEx_Sink, state); + ILibChain_AddWaitHandleEx(chain, p->hEvent, -1, ILibChain_ReadEx_Sink, state, metadata); } else { @@ -3189,21 +3270,23 @@ void __stdcall ILibChain_AddWaitHandle_apc(ULONG_PTR u) int msTIMEOUT = (int)(uintptr_t)((void**)u)[2]; ILibChain_WaitHandleHandler handler = (ILibChain_WaitHandleHandler)((void**)u)[3]; void *user = ((void**)u)[4]; + void *metadata = (char*)((void**)u)[5]; - ILibChain_AddWaitHandle(chain, h, msTIMEOUT, handler, user); + ILibChain_AddWaitHandleEx(chain, h, msTIMEOUT, handler, user, metadata); ILibMemory_Free((void*)u); } -void ILibChain_AddWaitHandle(void *chain, HANDLE h, int msTIMEOUT, ILibChain_WaitHandleHandler handler, void *user) +void ILibChain_AddWaitHandleEx(void *chain, HANDLE h, int msTIMEOUT, ILibChain_WaitHandleHandler handler, void *user, char *metadata) { if (!ILibIsRunningOnChainThread(chain)) { - void **tmp = ILibMemory_SmartAllocate(5 * sizeof(void*)); + void **tmp = ILibMemory_SmartAllocate(6 * sizeof(void*)); tmp[0] = chain; tmp[1] = h; tmp[2] = (void*)(uintptr_t)msTIMEOUT; tmp[3] = handler; tmp[4] = user; + tmp[5] = metadata; QueueUserAPC((PAPCFUNC)ILibChain_AddWaitHandle_apc, ILibChain_GetMicrostackThreadHandle(chain), (ULONG_PTR)tmp); return; } @@ -3215,12 +3298,14 @@ void ILibChain_AddWaitHandle(void *chain, HANDLE h, int msTIMEOUT, ILibChain_Wai void *node = ILibLinkedList_AddTail(((ILibBaseChain*)chain)->auxSelectHandles, h); info = (ILibChain_WaitHandleInfo*)ILibMemory_Extra(node); info->node = node; + info->metadata = metadata; ILibForceUnBlockChain(chain); } else { ((ILibBaseChain*)chain)->currentHandle = NULL; info = ((ILibBaseChain*)chain)->currentInfo; + info->metadata = metadata; } if (info != NULL) { diff --git a/microstack/ILibParsers.h b/microstack/ILibParsers.h index 701a427..2b27c47 100644 --- a/microstack/ILibParsers.h +++ b/microstack/ILibParsers.h @@ -973,6 +973,7 @@ int ILibIsRunningOnChainThread(void* chain); void ILibChain_DisableWatchDog(void *chain); void *ILibChain_GetObjectForDescriptor(void *chain, int fd); char *ILibChain_GetMetaDataFromDescriptorSet(void *chain, fd_set *inr, fd_set *inw, fd_set *ine); + char *ILibChain_GetMetaDataFromDescriptorSetEx(void *chain, fd_set *inr, fd_set *inw, fd_set *ine); #ifdef WIN32 typedef void(*ILib_GenericReadHandler)(char *buffer, int bufferLen, int* bytesConsumed, void* user1, void *user2); typedef BOOL(*ILibChain_ReadEx_Handler)(void *chain, HANDLE h, ILibWaitHandle_ErrorStatus status, char *buffer, int bytesRead, void* user); @@ -994,11 +995,17 @@ int ILibIsRunningOnChainThread(void* chain); HANDLE fileHandle; OVERLAPPED *p; void *user; + char *metadata; }ILibChain_WriteEx_data; - void ILibChain_AddWaitHandle(void *chain, HANDLE h, int msTIMEOUT, ILibChain_WaitHandleHandler handler, void *user); + + void ILibChain_AddWaitHandleEx(void *chain, HANDLE h, int msTIMEOUT, ILibChain_WaitHandleHandler handler, void *user, char *metadata); + #define ILibChain_AddWaitHandle(chain, h, msTIMEOUT, handler, user) ILibChain_AddWaitHandleEx(chain, h, msTIMEOUT, handler, user, NULL) void ILibChain_RemoveWaitHandle(void *chain, HANDLE h); - void ILibChain_ReadEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_ReadEx_Handler handler, void *user); - ILibTransport_DoneState ILibChain_WriteEx(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_WriteEx_Handler handler, void *user); + void ILibChain_ReadEx2(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_ReadEx_Handler handler, void *user, char *metadata); + #define ILibChain_ReadEx(chain, h, overlapped, buffer, bufferLen, handler, user) ILibChain_ReadEx2(chain, h, overlapped, buffer, bufferLen, handler, user, NULL) + ILibTransport_DoneState ILibChain_WriteEx2(void *chain, HANDLE h, OVERLAPPED *p, char *buffer, int bufferLen, ILibChain_WriteEx_Handler handler, void *user, char *metadata); + #define ILibChain_WriteEx(chain, h, overlapped, buffer, bufferLen, handler, user) ILibChain_WriteEx2(chain, h, overlapped, buffer, bufferLen, handler, user, NULL) + #define tv2LTtv1(ptv1, ptv2) ((ptv2)->tv_sec < (ptv1)->tv_sec || ((ptv2)->tv_sec == (ptv1)->tv_sec && (ptv2)->tv_usec < (ptv1)->tv_usec)) #define tv2LTEtv1(ptv1, ptv2) (tv2LTtv1(ptv2,ptv1) || ((ptv2)->tv_sec == (ptv1)->tv_sec && (ptv2)->tv_usec <= (ptv1)->tv_usec)) #define tvnonzero(ptv) ((ptv)->tv_sec != 0 || (ptv)->tv_usec != 0) diff --git a/microstack/ILibProcessPipe.c b/microstack/ILibProcessPipe.c index ef292cf..6acc0c6 100644 --- a/microstack/ILibProcessPipe.c +++ b/microstack/ILibProcessPipe.c @@ -1271,6 +1271,7 @@ BOOL ILibProcessPipe_Process_OnExit(void *chain, HANDLE event, ILibWaitHandle_Er if ((j->stdOut->PAUSED != 0 && j->stdOut->totalRead > 0) || (j->stdErr->PAUSED != 0 && j->stdErr->totalRead > 0)) { j->hProcess_needAdd = 1; + return(TRUE); } else { @@ -1282,8 +1283,8 @@ BOOL ILibProcessPipe_Process_OnExit(void *chain, HANDLE event, ILibWaitHandle_Er { ILibProcessPipe_Process_Destroy(j); } + return(FALSE); } - return(TRUE); } #endif void ILibProcessPipe_Process_UpdateUserObject(ILibProcessPipe_Process module, void *userObj)