diff --git a/src/core/ev.c b/src/core/ev.c index 13138809..81d28b56 100644 --- a/src/core/ev.c +++ b/src/core/ev.c @@ -1808,14 +1808,16 @@ JanetAsyncStatus ev_machine_write(JanetListenerState *s, JanetAsyncEvent event) } else #endif { - // File handles in IOCP need to specify this if they are writing to the - // ends of files, like how this is used here. - // If the underlying resource doesn't support seeking - // byte offsets, they will be ignored - // but this otherwise writes to the end of the file in question - // Right now, os/open streams aren't seekable, so this works. - // for more details see the lpOverlapped parameter in - // https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile + /* + * File handles in IOCP need to specify this if they are writing to the + * ends of files, like how this is used here. + * If the underlying resource doesn't support seeking + * byte offsets, they will be ignored + * but this otherwise writes to the end of the file in question + * Right now, os/open streams aren't seekable, so this works. + * for more details see the lpOverlapped parameter in + * https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-writefile + */ state->overlapped.Offset = (DWORD) 0xFFFFFFFF; state->overlapped.OffsetHigh = (DWORD) 0xFFFFFFFF; status = WriteFile(s->stream->handle, bytes, len, NULL, &state->overlapped); diff --git a/src/core/os.c b/src/core/os.c index 1f519202..fcd2c279 100644 --- a/src/core/os.c +++ b/src/core/os.c @@ -353,6 +353,7 @@ static const JanetAbstractType ProcAT; #define JANET_PROC_OWNS_STDIN 16 #define JANET_PROC_OWNS_STDOUT 32 #define JANET_PROC_OWNS_STDERR 64 +#define JANET_PROC_ALLOW_ZOMBIE 128 typedef struct { int flags; #ifdef JANET_WINDOWS @@ -434,12 +435,14 @@ static int janet_proc_gc(void *p, size_t s) { JanetProc *proc = (JanetProc *) p; #ifdef JANET_WINDOWS if (!(proc->flags & JANET_PROC_CLOSED)) { - TerminateProcess(proc->pHandle, 1); + if (!(proc->flags & JANET_PROC_ALLOW_ZOMBIE)) { + TerminateProcess(proc->pHandle, 1); + } CloseHandle(proc->pHandle); CloseHandle(proc->tHandle); } #else - if (!(proc->flags & JANET_PROC_WAITED)) { + if (!(proc->flags & (JANET_PROC_WAITED | JANET_PROC_ALLOW_ZOMBIE))) { /* Kill and wait to prevent zombies */ kill(proc->pid, SIGKILL); int status; @@ -759,7 +762,7 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) { /* Get flags */ uint64_t flags = 0; if (argc > 1) { - flags = janet_getflags(argv, 1, "epx"); + flags = janet_getflags(argv, 1, "epxd"); } /* Get environment */ @@ -777,7 +780,7 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) { JanetHandle new_in = JANET_HANDLE_NONE, new_out = JANET_HANDLE_NONE, new_err = JANET_HANDLE_NONE; JanetHandle pipe_in = JANET_HANDLE_NONE, pipe_out = JANET_HANDLE_NONE, pipe_err = JANET_HANDLE_NONE; int pipe_errflag = 0; /* Track errors setting up pipes */ - int pipe_owner_flags = 0; + int pipe_owner_flags = (is_spawn && (flags & 0x8)) ? JANET_PROC_ALLOW_ZOMBIE : 0; /* Get optional redirections */ if (argc > 2) { @@ -1842,6 +1845,7 @@ static Janet os_open(int32_t argc, Janet *argv) { case 'W': shareMode |= FILE_SHARE_WRITE; break; + gg case 'H': flagsAndAttributes |= FILE_ATTRIBUTE_HIDDEN; break; @@ -2094,12 +2098,13 @@ static const JanetReg os_cfuns[] = { "os/execute", os_execute, JDOC("(os/execute args &opt flags env)\n\n" "Execute a program on the system and pass it string arguments. `flags` " - "is a keyword that modifies how the program will execute.\n\n" + "is a keyword that modifies how the program will execute.\n" "* :e - enables passing an environment to the program. Without :e, the " - "current environment is inherited.\n\n" + "current environment is inherited.\n" "* :p - allows searching the current PATH for the binary to execute. " - "Without this flag, binaries must use absolute paths.\n\n" - "* :x - raise error if exit code is non-zero.\n\n" + "Without this flag, binaries must use absolute paths.\n" + "* :x - raise error if exit code is non-zero.\n" + "* :d - Don't try and terminate the process on garbage collection (allow spawning zombies).\n" "`env` is a table or struct mapping environment variables to values. It can also " "contain the keys :in, :out, and :err, which allow redirecting stdio in the subprocess. " "These arguments should be core/file values. "