diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 425930b079..5e11108335 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -21,10 +21,8 @@ jobs: shell: msys2 {0} run: | # XXX: cygwin still uses gcc v11 so we get new warnings with v13, - # resulting in errors. We can't selectively disable warnigns since our - # cross compiler is also too old and doesn't understand the new - # warning flags, so we need to disable all errors for now. - export CXXFLAGS="-Wno-error -Wno-narrowing" + # resulting in errors due to -Werror. Disable them for now. + export CXXFLAGS="-Wno-error=stringop-truncation -Wno-error=array-bounds -Wno-error=overloaded-virtual -Wno-narrowing -Wno-use-after-free" (cd winsup && ./autogen.sh) ./configure --disable-dependency-tracking make -j8 diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc index 1fe72fc8b8..f9a6946d9f 100644 --- a/winsup/cygwin/fhandler/console.cc +++ b/winsup/cygwin/fhandler/console.cc @@ -4344,8 +4344,6 @@ fhandler_console::need_console_handler () void fhandler_console::set_disable_master_thread (bool x, fhandler_console *cons) { - if (con.disable_master_thread == x) - return; if (cons == NULL) { if (cygheap->ctty && cygheap->ctty->get_major () == DEV_CONS_MAJOR) diff --git a/winsup/cygwin/fhandler/pipe.cc b/winsup/cygwin/fhandler/pipe.cc index 283319cce8..8daae8d192 100644 --- a/winsup/cygwin/fhandler/pipe.cc +++ b/winsup/cygwin/fhandler/pipe.cc @@ -18,6 +18,7 @@ details. */ #include "pinfo.h" #include "shared_info.h" #include "tls_pbuf.h" +#include "sigproc.h" #include /* This is only to be used for writing. When reading, @@ -587,6 +588,17 @@ fhandler_pipe::fixup_after_fork (HANDLE parent) ReleaseMutex (hdl_cnt_mtx); } +void +fhandler_pipe::fixup_after_exec () +{ + /* Set read pipe itself always non-blocking for cygwin process. + Blocking/non-blocking is simulated in raw_read(). For write + pipe, follow is_nonblocking(). */ + bool mode = get_device () == FH_PIPEW ? is_nonblocking () : true; + set_pipe_non_blocking (mode); + fhandler_base::fixup_after_exec (); +} + int fhandler_pipe::dup (fhandler_base *child, int flags) { @@ -1207,53 +1219,24 @@ HANDLE fhandler_pipe::get_query_hdl_per_process (WCHAR *name, OBJECT_NAME_INFORMATION *ntfn) { - NTSTATUS status; - ULONG len; - DWORD n_process = 256; - PSYSTEM_PROCESS_INFORMATION spi; - do - { /* Enumerate processes */ - DWORD nbytes = n_process * sizeof (SYSTEM_PROCESS_INFORMATION); - spi = (PSYSTEM_PROCESS_INFORMATION) HeapAlloc (GetProcessHeap (), - 0, nbytes); - if (!spi) - return NULL; - status = NtQuerySystemInformation (SystemProcessInformation, - spi, nbytes, &len); - if (NT_SUCCESS (status)) - break; - HeapFree (GetProcessHeap (), 0, spi); - n_process *= 2; - } - while (n_process < (1L<<20) && status == STATUS_INFO_LENGTH_MISMATCH); - if (!NT_SUCCESS (status)) - return NULL; + winpids pids ((DWORD) 0); - /* In most cases, it is faster to check the processes in reverse order. - To do this, store PIDs into an array. */ - DWORD *proc_pids = (DWORD *) HeapAlloc (GetProcessHeap (), 0, - n_process * sizeof (DWORD)); - if (!proc_pids) + /* In most cases, it is faster to check the processes in reverse order. */ + for (LONG i = (LONG) pids.npids - 1; i >= 0; i--) { - HeapFree (GetProcessHeap (), 0, spi); - return NULL; - } - PSYSTEM_PROCESS_INFORMATION p = spi; - n_process = 0; - while (true) - { - proc_pids[n_process++] = (DWORD)(intptr_t) p->UniqueProcessId; - if (!p->NextEntryOffset) - break; - p = (PSYSTEM_PROCESS_INFORMATION) ((char *) p + p->NextEntryOffset); - } - HeapFree (GetProcessHeap (), 0, spi); + NTSTATUS status; + ULONG len; + + /* Non-cygwin app may call ReadFile() for empty pipe, which makes + NtQueryObject() for ObjectNameInformation block. Therefore, do + not try to get query_hdl for non-cygwin apps. */ + _pinfo *p = pids[i]; + if (!p || ISSTATE (p, PID_NOTCYGWIN)) + continue; - for (LONG i = (LONG) n_process - 1; i >= 0; i--) - { HANDLE proc = OpenProcess (PROCESS_DUP_HANDLE | PROCESS_QUERY_INFORMATION, - 0, proc_pids[i]); + 0, p->dwProcessId); if (!proc) continue; @@ -1317,7 +1300,6 @@ fhandler_pipe::get_query_hdl_per_process (WCHAR *name, query_hdl_proc = proc; query_hdl_value = (HANDLE)(intptr_t) phi->Handles[j].HandleValue; HeapFree (GetProcessHeap (), 0, phi); - HeapFree (GetProcessHeap (), 0, proc_pids); return h; } close_handle: @@ -1327,7 +1309,6 @@ fhandler_pipe::get_query_hdl_per_process (WCHAR *name, close_proc: CloseHandle (proc); } - HeapFree (GetProcessHeap (), 0, proc_pids); return NULL; } @@ -1401,3 +1382,54 @@ fhandler_pipe::get_query_hdl_per_system (WCHAR *name, HeapFree (GetProcessHeap (), 0, shi); return NULL; } + +void +fhandler_pipe::spawn_worker (int fileno_stdin, int fileno_stdout, + int fileno_stderr) +{ + bool need_send_noncygchld_sig = false; + + /* spawn_worker() is called from spawn.cc only when non-cygwin app + is started. Set pipe mode blocking for the non-cygwin process. */ + int fd; + cygheap_fdenum cfd (false); + while ((fd = cfd.next ()) >= 0) + if (cfd->get_dev () == FH_PIPEW + && (fd == fileno_stdout || fd == fileno_stderr)) + { + fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd; + pipe->set_pipe_non_blocking (false); + + /* Setup for query_ndl stuff. Read the comment below. */ + if (pipe->request_close_query_hdl ()) + need_send_noncygchld_sig = true; + } + else if (cfd->get_dev () == FH_PIPER && fd == fileno_stdin) + { + fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd; + pipe->set_pipe_non_blocking (false); + } + + /* If multiple writers including non-cygwin app exist, the non-cygwin + app cannot detect pipe closure on the read side when the pipe is + created by system account or the pipe creator is running as service. + This is because query_hdl which is held in write side also is a read + end of the pipe, so the pipe is still alive for the non-cygwin app + even after the reader is closed. + + To avoid this problem, let all processes in the same process + group close query_hdl using internal signal __SIGNONCYGCHLD when + non-cygwin app is started. */ + if (need_send_noncygchld_sig) + { + tty_min dummy_tty; + dummy_tty.ntty = (fh_devices) myself->ctty; + dummy_tty.pgid = myself->pgid; + tty_min *t = cygwin_shared->tty.get_cttyp (); + if (!t) /* If tty is not allocated, use dummy_tty instead. */ + t = &dummy_tty; + /* Emit __SIGNONCYGCHLD to let all processes in the + process group close query_hdl. */ + t->kill_pgrp (__SIGNONCYGCHLD); + } +} diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h index 649a431844..15b19f7643 100644 --- a/winsup/cygwin/local_includes/fhandler.h +++ b/winsup/cygwin/local_includes/fhandler.h @@ -1212,6 +1212,7 @@ class fhandler_pipe: public fhandler_pipe_fifo int open (int flags, mode_t mode = 0); bool open_setup (int flags); void fixup_after_fork (HANDLE); + void fixup_after_exec (); int dup (fhandler_base *child, int); void set_close_on_exec (bool val); int close (); @@ -1273,6 +1274,8 @@ class fhandler_pipe: public fhandler_pipe_fifo } return false; } + static void spawn_worker (int fileno_stdin, int fileno_stdout, + int fileno_stderr); }; #define CYGWIN_FIFO_PIPE_NAME_LEN 47 diff --git a/winsup/cygwin/msys2_path_conv.cc b/winsup/cygwin/msys2_path_conv.cc index 133939a7a8..1c60bf375c 100644 --- a/winsup/cygwin/msys2_path_conv.cc +++ b/winsup/cygwin/msys2_path_conv.cc @@ -366,7 +366,6 @@ path_type find_path_start_and_type(const char** src, int recurse, const char* en switch (*it) { case '`': case '\'': - case '"': case '*': case '?': case '[': diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc index 383f5e56fe..acdef49375 100644 --- a/winsup/cygwin/spawn.cc +++ b/winsup/cygwin/spawn.cc @@ -607,38 +607,8 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv, int fileno_stderr = 2; if (!iscygwin ()) - { - bool need_send_sig = false; - int fd; - cygheap_fdenum cfd (false); - while ((fd = cfd.next ()) >= 0) - if (cfd->get_dev () == FH_PIPEW - && (fd == fileno_stdout || fd == fileno_stderr)) - { - fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd; - pipe->set_pipe_non_blocking (false); - if (pipe->request_close_query_hdl ()) - need_send_sig = true; - } - else if (cfd->get_dev () == FH_PIPER && fd == fileno_stdin) - { - fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd; - pipe->set_pipe_non_blocking (false); - } - - if (need_send_sig) - { - tty_min dummy_tty; - dummy_tty.ntty = (fh_devices) myself->ctty; - dummy_tty.pgid = myself->pgid; - tty_min *t = cygwin_shared->tty.get_cttyp (); - if (!t) /* If tty is not allocated, use dummy_tty instead. */ - t = &dummy_tty; - /* Emit __SIGNONCYGCHLD to let all processes in the - process group close query_hdl. */ - t->kill_pgrp (__SIGNONCYGCHLD); - } - } + fhandler_pipe::spawn_worker (fileno_stdin, fileno_stdout, + fileno_stderr); bool no_pcon = mode != _P_OVERLAY && mode != _P_WAIT; term_spawn_worker.setup (iscygwin (), handle (fileno_stdin, false),