mirror of
https://github.com/janet-lang/janet
synced 2025-04-27 05:03:14 +00:00
Fix subprocess spawning on windows.
Also fix (:read stream :all)
This commit is contained in:
parent
4df1ac5b23
commit
f0dbc2e404
@ -955,7 +955,7 @@ JanetListenerState *janet_listen(JanetStream *stream, JanetListener behavior, in
|
|||||||
JanetListenerState *state = janet_listen_impl(stream, behavior, mask, size, user);
|
JanetListenerState *state = janet_listen_impl(stream, behavior, mask, size, user);
|
||||||
if (!(stream->flags & JANET_STREAM_IOCP)) {
|
if (!(stream->flags & JANET_STREAM_IOCP)) {
|
||||||
if (NULL == CreateIoCompletionPort(stream->handle, janet_vm_iocp, (ULONG_PTR) stream, 0)) {
|
if (NULL == CreateIoCompletionPort(stream->handle, janet_vm_iocp, (ULONG_PTR) stream, 0)) {
|
||||||
janet_panic("failed to listen for events");
|
janet_panicf("failed to listen for events: %V", janet_ev_lasterr());
|
||||||
}
|
}
|
||||||
stream->flags |= JANET_STREAM_IOCP;
|
stream->flags |= JANET_STREAM_IOCP;
|
||||||
}
|
}
|
||||||
@ -1587,7 +1587,7 @@ JanetAsyncStatus ev_machine_read(JanetListenerState *s, JanetAsyncEvent event) {
|
|||||||
case JANET_ASYNC_EVENT_READ: {
|
case JANET_ASYNC_EVENT_READ: {
|
||||||
JanetBuffer *buffer = state->buf;
|
JanetBuffer *buffer = state->buf;
|
||||||
int32_t bytes_left = state->bytes_left;
|
int32_t bytes_left = state->bytes_left;
|
||||||
int32_t read_limit = bytes_left < 0 ? 4096 : bytes_left;
|
int32_t read_limit = bytes_left > 4096 ? 4096 : bytes_left;
|
||||||
janet_buffer_extra(buffer, read_limit);
|
janet_buffer_extra(buffer, read_limit);
|
||||||
ssize_t nread;
|
ssize_t nread;
|
||||||
#ifdef JANET_NET
|
#ifdef JANET_NET
|
||||||
@ -1923,6 +1923,10 @@ int janet_make_pipe(JanetHandle handles[2]) {
|
|||||||
*/
|
*/
|
||||||
JanetHandle rhandle, whandle;
|
JanetHandle rhandle, whandle;
|
||||||
UCHAR PipeNameBuffer[MAX_PATH];
|
UCHAR PipeNameBuffer[MAX_PATH];
|
||||||
|
SECURITY_ATTRIBUTES saAttr;
|
||||||
|
memset(&saAttr, 0, sizeof(saAttr));
|
||||||
|
saAttr.nLength = sizeof(saAttr);
|
||||||
|
saAttr.bInheritHandle = TRUE;
|
||||||
sprintf(PipeNameBuffer,
|
sprintf(PipeNameBuffer,
|
||||||
"\\\\.\\Pipe\\JanetPipeFile.%08x.%08x",
|
"\\\\.\\Pipe\\JanetPipeFile.%08x.%08x",
|
||||||
GetCurrentProcessId(),
|
GetCurrentProcessId(),
|
||||||
@ -1931,17 +1935,17 @@ int janet_make_pipe(JanetHandle handles[2]) {
|
|||||||
PipeNameBuffer,
|
PipeNameBuffer,
|
||||||
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
|
PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
|
||||||
PIPE_TYPE_BYTE | PIPE_NOWAIT,
|
PIPE_TYPE_BYTE | PIPE_NOWAIT,
|
||||||
1, /* Number of pipes */
|
255, /* Max number of pipes for duplication. */
|
||||||
4096, /* Out buffer size */
|
4096, /* Out buffer size */
|
||||||
4096, /* In buffer size */
|
4096, /* In buffer size */
|
||||||
120 * 1000, /* Timeout in ms */
|
120 * 1000, /* Timeout in ms */
|
||||||
NULL);
|
&saAttr);
|
||||||
if (!rhandle) return -1;
|
if (!rhandle) return -1;
|
||||||
whandle = CreateFileA(
|
whandle = CreateFileA(
|
||||||
PipeNameBuffer,
|
PipeNameBuffer,
|
||||||
GENERIC_WRITE,
|
GENERIC_WRITE,
|
||||||
0,
|
0,
|
||||||
NULL,
|
&saAttr,
|
||||||
OPEN_EXISTING,
|
OPEN_EXISTING,
|
||||||
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
|
||||||
NULL);
|
NULL);
|
||||||
@ -2058,7 +2062,7 @@ Janet janet_cfun_stream_read(int32_t argc, Janet *argv) {
|
|||||||
double to = janet_optnumber(argv, argc, 3, INFINITY);
|
double to = janet_optnumber(argv, argc, 3, INFINITY);
|
||||||
if (janet_keyeq(argv[1], "all")) {
|
if (janet_keyeq(argv[1], "all")) {
|
||||||
if (to != INFINITY) janet_addtimeout(to);
|
if (to != INFINITY) janet_addtimeout(to);
|
||||||
janet_ev_readchunk(stream, buffer, -1);
|
janet_ev_readchunk(stream, buffer, INT32_MAX);
|
||||||
} else {
|
} else {
|
||||||
int32_t n = janet_getnat(argv, 1);
|
int32_t n = janet_getnat(argv, 1);
|
||||||
if (to != INFINITY) janet_addtimeout(to);
|
if (to != INFINITY) janet_addtimeout(to);
|
||||||
|
@ -527,10 +527,24 @@ static void close_handle(JanetHandle handle) {
|
|||||||
/* Create piped file for os/execute and os/spawn. Need to be careful that we mark
|
/* Create piped file for os/execute and os/spawn. Need to be careful that we mark
|
||||||
the error flag if we can't create pipe and don't leak handles. *handle will be cleaned
|
the error flag if we can't create pipe and don't leak handles. *handle will be cleaned
|
||||||
up by the calling function. If everything goes well, *handle is owned by the calling function,
|
up by the calling function. If everything goes well, *handle is owned by the calling function,
|
||||||
(if it is set) and the returned JanetFile owns the other end of the pipe, which will be closed
|
(if it is set) and the returned handle owns the other end of the pipe, which will be closed
|
||||||
on GC or fclose. */
|
on GC or fclose. */
|
||||||
static JanetHandle make_pipes(JanetHandle *handle, int reverse, int *errflag) {
|
static JanetHandle make_pipes(JanetHandle *handle, int reverse, int *errflag) {
|
||||||
JanetHandle handles[2];
|
JanetHandle handles[2];
|
||||||
|
#ifdef JANET_EV
|
||||||
|
|
||||||
|
/* non-blocking pipes */
|
||||||
|
if (janet_make_pipe(handles)) goto error;
|
||||||
|
if (reverse) swap_handles(handles);
|
||||||
|
#ifdef JANET_WINDOWS
|
||||||
|
if (!SetHandleInformation(handles[0], HANDLE_FLAG_INHERIT, 0)) goto error;
|
||||||
|
#endif
|
||||||
|
*handle = handles[1];
|
||||||
|
return handles[0];
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
/* Normal blocking pipes */
|
||||||
#ifdef JANET_WINDOWS
|
#ifdef JANET_WINDOWS
|
||||||
SECURITY_ATTRIBUTES saAttr;
|
SECURITY_ATTRIBUTES saAttr;
|
||||||
memset(&saAttr, 0, sizeof(saAttr));
|
memset(&saAttr, 0, sizeof(saAttr));
|
||||||
@ -548,6 +562,8 @@ static JanetHandle make_pipes(JanetHandle *handle, int reverse, int *errflag) {
|
|||||||
*handle = handles[1];
|
*handle = handles[1];
|
||||||
return handles[0];
|
return handles[0];
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
error:
|
error:
|
||||||
*errflag = 1;
|
*errflag = 1;
|
||||||
return JANET_HANDLE_NONE;
|
return JANET_HANDLE_NONE;
|
||||||
@ -736,7 +752,6 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) {
|
|||||||
startupInfo.cb = sizeof(startupInfo);
|
startupInfo.cb = sizeof(startupInfo);
|
||||||
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
|
startupInfo.dwFlags |= STARTF_USESTDHANDLES;
|
||||||
saAttr.nLength = sizeof(saAttr);
|
saAttr.nLength = sizeof(saAttr);
|
||||||
saAttr.bInheritHandle = TRUE;
|
|
||||||
|
|
||||||
JanetBuffer *buf = os_exec_escape(exargs);
|
JanetBuffer *buf = os_exec_escape(exargs);
|
||||||
if (buf->count > 8191) {
|
if (buf->count > 8191) {
|
||||||
@ -862,9 +877,6 @@ static Janet os_execute_impl(int32_t argc, Janet *argv, int is_spawn) {
|
|||||||
if (status) {
|
if (status) {
|
||||||
os_execute_cleanup(envp, child_argv);
|
os_execute_cleanup(envp, child_argv);
|
||||||
janet_panicf("%p: %s", argv[0], strerror(errno));
|
janet_panicf("%p: %s", argv[0], strerror(errno));
|
||||||
} else if (is_spawn) {
|
|
||||||
/* Get process handle */
|
|
||||||
os_execute_cleanup(envp, child_argv);
|
|
||||||
} else {
|
} else {
|
||||||
/* Wait to complete */
|
/* Wait to complete */
|
||||||
os_execute_cleanup(envp, child_argv);
|
os_execute_cleanup(envp, child_argv);
|
||||||
|
@ -83,9 +83,16 @@
|
|||||||
|
|
||||||
(assert-error "bad arity to ev/call" (ev/call inc 1 2 3))
|
(assert-error "bad arity to ev/call" (ev/call inc 1 2 3))
|
||||||
|
|
||||||
|
(assert (os/execute [(dyn :executable) "-e" `(+ 1 2 3)`] :xp) "os/execute self")
|
||||||
|
|
||||||
# Subprocess
|
# Subprocess
|
||||||
|
(let [p (os/spawn [(dyn :executable) "-e" `(file/read stdin :line)`] :px {:in :pipe})]
|
||||||
|
(:write (p :in) "hello!")
|
||||||
|
(assert-no-error "pipe stdin to process" (os/proc-wait p)))
|
||||||
|
|
||||||
(let [p (os/spawn [(dyn :executable) "-e" `(print "hello")`] :p {:out :pipe})]
|
(let [p (os/spawn [(dyn :executable) "-e" `(print "hello")`] :p {:out :pipe})]
|
||||||
(assert (deep= @"hello\n" (:read (p :out) :all)) "capture stdout from os/spawn")
|
(os/proc-wait p)
|
||||||
(os/proc-wait p))
|
(def x (:read (p :out) 1024))
|
||||||
|
(assert (deep= "hello" (string/trim x)) "capture stdout from os/spawn"))
|
||||||
|
|
||||||
(end-suite)
|
(end-suite)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user