diff options
-rw-r--r-- | winsup/cygwin/devices.cc | 4 | ||||
-rw-r--r-- | winsup/cygwin/devices.in | 4 | ||||
-rw-r--r-- | winsup/cygwin/exceptions.cc | 3 | ||||
-rw-r--r-- | winsup/cygwin/fhandler/console.cc | 162 | ||||
-rw-r--r-- | winsup/cygwin/fhandler/dsp.cc | 26 | ||||
-rw-r--r-- | winsup/cygwin/fhandler/pty.cc | 25 | ||||
-rw-r--r-- | winsup/cygwin/local_includes/fhandler.h | 20 | ||||
-rw-r--r-- | winsup/cygwin/local_includes/shared_info.h | 3 | ||||
-rw-r--r-- | winsup/cygwin/local_includes/tty.h | 5 | ||||
-rw-r--r-- | winsup/cygwin/release/3.5.4 | 7 |
10 files changed, 178 insertions, 81 deletions
diff --git a/winsup/cygwin/devices.cc b/winsup/cygwin/devices.cc index d4c003b..6eb6a41 100644 --- a/winsup/cygwin/devices.cc +++ b/winsup/cygwin/devices.cc @@ -83,8 +83,8 @@ exists_console (const device& dev) default: if (dev.get_minor () < MAX_CONS_DEV) { - unsigned long bitmask = fhandler_console::console_unit (CONS_LIST_USED); - return !!(bitmask & (1UL << dev.get_minor ())); + int n = fhandler_console::console_unit (dev.get_minor ()); + return (n == dev.get_minor ()); } return false; } diff --git a/winsup/cygwin/devices.in b/winsup/cygwin/devices.in index a86e501..ea9a70e 100644 --- a/winsup/cygwin/devices.in +++ b/winsup/cygwin/devices.in @@ -79,8 +79,8 @@ exists_console (const device& dev) default: if (dev.get_minor () < MAX_CONS_DEV) { - unsigned long bitmask = fhandler_console::console_unit (CONS_LIST_USED); - return !!(bitmask & (1UL << dev.get_minor ())); + int n = fhandler_console::console_unit (dev.get_minor ()); + return (n == dev.get_minor ()); } return false; } diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index a2a6f9d..28d0431 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -1717,7 +1717,10 @@ _cygtls::call_signal_handler () context, unwind to the caller and in case we're called from sigdelayed, fix the instruction pointer accordingly. */ context.uc_mcontext.ctxflags = CONTEXT_FULL; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wmaybe-uninitialized" RtlCaptureContext ((PCONTEXT) &context.uc_mcontext); +#pragma GCC diagnostic pop __unwind_single_frame ((PCONTEXT) &context.uc_mcontext); if (stackptr > stack) { diff --git a/winsup/cygwin/fhandler/console.cc b/winsup/cygwin/fhandler/console.cc index 1c0d5c8..d4c3f10 100644 --- a/winsup/cygwin/fhandler/console.cc +++ b/winsup/cygwin/fhandler/console.cc @@ -33,6 +33,7 @@ details. */ #include "child_info.h" #include "cygwait.h" #include "winf.h" +#include "psapi.h" /* Don't make this bigger than NT_MAX_PATH as long as the temporary buffer is allocated using tmp_pathbuf!!! */ @@ -48,6 +49,9 @@ details. */ con.b.srWindow.Top + con.scroll_region.Bottom) #define con_is_legacy (shared_console_info[unit] && con.is_legacy) +static HANDLE NO_COPY shared_info_mutex; +static int NO_COPY shared_info_state[MAX_CONS_DEV]; + #define CONS_THREAD_SYNC "cygcons.thread_sync" static bool NO_COPY master_thread_started = false; @@ -224,44 +228,52 @@ fhandler_console::open_shared_console (HWND hw, HANDLE& h, bool& created) return res; } -BOOL CALLBACK -fhandler_console::enum_windows (HWND hw, LPARAM lp) +fhandler_console::console_unit::console_unit (int n0, HANDLE *input_mutex) : + n (-1) { - console_unit *this1 = (console_unit *) lp; - HANDLE h = NULL; - fhandler_console::console_state *cs; - if ((cs = fhandler_console::open_shared_console (hw, h))) + char buf[MAX_PATH]; + for (int i = max(0, n0); i < MAX_CONS_DEV; i++) { - CloseHandle (h); - if (major (cs->tty_min_state.getntty ()) == DEV_CONS_MAJOR) - this1->bitmask |= 1UL << minor (cs->tty_min_state.getntty ()); - if (this1->n == minor (cs->tty_min_state.getntty ())) + shared_name (buf, "cygcons.input.mutex", i); + SetLastError (ERROR_SUCCESS); + HANDLE input_mutex0 = CreateMutex (&sec_none, FALSE, buf); + DWORD err = GetLastError (); + if (err == ERROR_ALREADY_EXISTS || err == ERROR_ACCESS_DENIED) { - this1->shared_console_info = cs; - return FALSE; + if (n0 >= 0) + n = i; } - UnmapViewOfFile ((void *) cs); + else if (n0 == CONS_SCAN_UNUSED) + { + n = i; + if (input_mutex) + *input_mutex = input_mutex0; + break; + } + if (input_mutex0) + CloseHandle (input_mutex0); + if (n0 >= 0) + break; } - else - { /* Only for ConEmu */ - char class_hw[32]; - if (19 == GetClassName (hw, class_hw, sizeof (class_hw)) - && 0 == strcmp (class_hw, "VirtualConsoleClass")) - EnumChildWindows (hw, fhandler_console::enum_windows, lp); + if (n0 == CONS_SCAN_UNUSED && n < 0) + { + __small_sprintf (buf, "console device allocation failure - " + "too many consoles in use, max consoles is %d", + MAX_CONS_DEV); + api_fatal (buf); } - return TRUE; } -fhandler_console::console_unit::console_unit (int n0): - n (n0), bitmask (0), shared_console_info (NULL) +fhandler_console::console_unit::operator console_state * () const { - EnumWindows (fhandler_console::enum_windows, (LPARAM) this); - if (n0 == CONS_SCAN_UNUSED && (n = ffsl (~bitmask) - 1) < 0) - api_fatal (sizeof (bitmask) == 8 ? - "console device allocation failure - " - "too many consoles in use, max consoles is 64" : - "console device allocation failure - " - "too many consoles in use, max consoles is 32"); + if (n < 0 || n >= MAX_CONS_DEV) + return NULL; + HANDLE h = NULL; + fhandler_console::console_state *cs; + HWND hw = cygwin_shared->cons_hwnd[n]; + if ((cs = fhandler_console::open_shared_console (hw, h))) + CloseHandle (h); + return cs; } static DWORD @@ -272,17 +284,23 @@ cons_master_thread (VOID *arg) fhandler_console::handle_set_t handle_set; fh->get_duplicated_handle_set (&handle_set); HANDLE thread_sync_event; - DuplicateHandle (GetCurrentProcess (), fh->thread_sync_event, - GetCurrentProcess (), &thread_sync_event, - 0, FALSE, DUPLICATE_SAME_ACCESS); - SetEvent (thread_sync_event); - master_thread_started = true; - /* Do not touch class members after here because the class instance - may have been destroyed. */ - fhandler_console::cons_master_thread (&handle_set, ttyp); - fhandler_console::close_handle_set (&handle_set); - SetEvent (thread_sync_event); - CloseHandle (thread_sync_event); + if (DuplicateHandle (GetCurrentProcess (), fh->thread_sync_event, + GetCurrentProcess (), &thread_sync_event, + 0, FALSE, DUPLICATE_SAME_ACCESS)) + { + SetEvent (thread_sync_event); + master_thread_started = true; + /* Do not touch class members after here because the class instance + may have been destroyed. */ + fhandler_console::cons_master_thread (&handle_set, ttyp); + fhandler_console::close_handle_set (&handle_set); + SetEvent (thread_sync_event); + CloseHandle (thread_sync_event); + master_thread_started = false; + } + else + debug_printf ("cons_master_thread not started because thread_sync_event " + "could not be duplicated %08x", GetLastError ()); return 0; } @@ -451,6 +469,8 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp) case WAIT_CANCELED: break; default: /* Error */ + free (input_rec); + free (input_tmp); ReleaseMutex (p->input_mutex); return; } @@ -650,6 +670,11 @@ fhandler_console::set_unit () else if (myself->ctty != CTTY_UNINITIALIZED) unit = device::minor (myself->ctty); + if (!shared_info_mutex) + shared_info_mutex = CreateMutex (&sec_none_nih, FALSE, NULL); + + WaitForSingleObject (shared_info_mutex, INFINITE); + if (shared_console_info[unit]) ; /* Do nothing */ else if (generic_console @@ -658,7 +683,10 @@ fhandler_console::set_unit () else { if (!generic_console && (dev_t) myself->ctty != get_device ()) - shared_console_info[unit] = console_unit (unit); + { + shared_console_info[unit] = console_unit (unit); + shared_info_state[unit]++; + } if (generic_console || !shared_console_info[unit]) { me = GetConsoleWindow (); @@ -669,10 +697,12 @@ fhandler_console::set_unit () created = true; fhandler_console::console_state *cs = open_shared_console (me, cygheap->console_h, created); + shared_info_state[unit]++; ProtectHandleINH (cygheap->console_h); if (created) { - unit = console_unit (CONS_SCAN_UNUSED); + unit = console_unit (CONS_SCAN_UNUSED, &input_mutex); + cygwin_shared->cons_hwnd[unit] = me; cs->tty_min_state.setntty (DEV_CONS_MAJOR, unit); } else @@ -683,6 +713,8 @@ fhandler_console::set_unit () } } } + ReleaseMutex (shared_info_mutex); + if (shared_console_info[unit]) { devset = (fh_devices) shared_console_info[unit]->tty_min_state.getntty (); @@ -1847,9 +1879,15 @@ fhandler_console::open (int flags, mode_t) char name[MAX_PATH]; shared_name (name, CONS_THREAD_SYNC, get_minor ()); thread_sync_event = CreateEvent(NULL, FALSE, FALSE, name); - new cygthread (::cons_master_thread, this, "consm"); - WaitForSingleObject (thread_sync_event, INFINITE); - CloseHandle (thread_sync_event); + if (thread_sync_event) + { + new cygthread (::cons_master_thread, this, "consm"); + WaitForSingleObject (thread_sync_event, INFINITE); + CloseHandle (thread_sync_event); + } + else + debug_printf ("Failed to create thread_sync_event %08x", + GetLastError ()); } return 1; } @@ -1910,9 +1948,15 @@ fhandler_console::close () char name[MAX_PATH]; shared_name (name, CONS_THREAD_SYNC, get_minor ()); thread_sync_event = OpenEvent (MAXIMUM_ALLOWED, FALSE, name); - con.owner = MAX_PID + 1; - WaitForSingleObject (thread_sync_event, INFINITE); - CloseHandle (thread_sync_event); + if (thread_sync_event) + { + con.owner = MAX_PID + 1; + WaitForSingleObject (thread_sync_event, INFINITE); + CloseHandle (thread_sync_event); + } + else + debug_printf ("Failed to open thread_sync_event %08x", + GetLastError ()); } con.owner = 0; } @@ -1927,7 +1971,23 @@ fhandler_console::close () if (!have_execed && !invisible_console && (!CTTY_IS_VALID (myself->ctty) || get_device () == (dev_t) myself->ctty)) - free_console (); + { + /* ConEmu hack. Detach from ConEmu to unhook console APIs. */ + HMODULE h = GetModuleHandle ("ConEmuHk64.dll"); + if (h) + { + MODULEINFO mi; + if (GetModuleInformation (GetCurrentProcess (), h, &mi, sizeof (mi))) + { + BOOL (*DllMain)(HINSTANCE, DWORD, LPVOID) = + (BOOL (*)(HINSTANCE, DWORD, LPVOID)) mi.EntryPoint; + DllMain (h, DLL_PROCESS_DETACH, NULL); + } + } + + /* Freeing console to detach the process from the console. */ + free_console (); + } release_output_mutex (); @@ -1936,11 +1996,13 @@ fhandler_console::close () CloseHandle (output_mutex); output_mutex = NULL; - if (shared_console_info[unit] && myself->ctty != tc ()->ntty) + WaitForSingleObject (shared_info_mutex, INFINITE); + if (--shared_info_state[unit] == 0 && shared_console_info[unit]) { UnmapViewOfFile ((void *) shared_console_info[unit]); shared_console_info[unit] = NULL; } + ReleaseMutex (shared_info_mutex); return 0; } diff --git a/winsup/cygwin/fhandler/dsp.cc b/winsup/cygwin/fhandler/dsp.cc index 59c11ac..605a048 100644 --- a/winsup/cygwin/fhandler/dsp.cc +++ b/winsup/cygwin/fhandler/dsp.cc @@ -1026,19 +1026,19 @@ fhandler_dev_dsp::fhandler_dev_dsp (): ssize_t fhandler_dev_dsp::write (const void *ptr, size_t len) { - return base ()->_write (ptr, len); + return base ()->_write (ptr, len, this); } void fhandler_dev_dsp::read (void *ptr, size_t& len) { - base ()->_read (ptr, len); + base ()->_read (ptr, len, this); } int fhandler_dev_dsp::ioctl (unsigned int cmd, void *buf) { - return base ()->_ioctl (cmd, buf); + return base ()->_ioctl (cmd, buf, this); } int @@ -1065,7 +1065,6 @@ fhandler_dev_dsp::open (int flags, mode_t mode) { int ret = -1, err = 0; UINT num_in = 0, num_out = 0; - set_flags ((flags & ~O_TEXT) | O_BINARY); // Work out initial sample format & frequency, /dev/dsp defaults audioformat_ = AFMT_U8; audiofreq_ = 8000; @@ -1105,11 +1104,11 @@ fhandler_dev_dsp::open (int flags, mode_t mode) return ret; } -#define IS_WRITE() ((get_flags() & O_ACCMODE) != O_RDONLY) -#define IS_READ() ((get_flags() & O_ACCMODE) != O_WRONLY) +#define IS_WRITE() ((fh->get_flags() & O_ACCMODE) != O_RDONLY) +#define IS_READ() ((fh->get_flags() & O_ACCMODE) != O_WRONLY) ssize_t -fhandler_dev_dsp::_write (const void *ptr, size_t len) +fhandler_dev_dsp::_write (const void *ptr, size_t len, fhandler_dev_dsp *fh) { debug_printf ("ptr=%p len=%ld", ptr, len); int len_s = len; @@ -1168,7 +1167,7 @@ fhandler_dev_dsp::_write (const void *ptr, size_t len) } void -fhandler_dev_dsp::_read (void *ptr, size_t& len) +fhandler_dev_dsp::_read (void *ptr, size_t& len, fhandler_dev_dsp *fh) { debug_printf ("ptr=%p len=%ld", ptr, len); @@ -1244,7 +1243,7 @@ fhandler_dev_dsp::close () } int -fhandler_dev_dsp::_ioctl (unsigned int cmd, void *buf) +fhandler_dev_dsp::_ioctl (unsigned int cmd, void *buf, fhandler_dev_dsp *fh) { debug_printf ("audio_in=%p audio_out=%p", audio_in_, audio_out_); int *intbuf = (int *) buf; @@ -1349,7 +1348,7 @@ fhandler_dev_dsp::_ioctl (unsigned int cmd, void *buf) CASE (SNDCTL_DSP_STEREO) { int nChannels = *intbuf + 1; - int res = _ioctl (SNDCTL_DSP_CHANNELS, &nChannels); + int res = _ioctl (SNDCTL_DSP_CHANNELS, &nChannels, fh); *intbuf = nChannels - 1; return res; } @@ -1547,3 +1546,10 @@ fhandler_dev_dsp::read_ready () { return base ()->_read_ready (); } + +bool +fhandler_dev_dsp::open_setup (int flags) +{ + set_flags ((flags & ~O_TEXT) | O_BINARY); + return fhandler_base::open_setup (flags); +} diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc index 9d7ef3c..fa6bf10 100644 --- a/winsup/cygwin/fhandler/pty.cc +++ b/winsup/cygwin/fhandler/pty.cc @@ -3118,8 +3118,22 @@ fhandler_pty_common::process_opost_output (HANDLE h, const void *ptr, return res; /* Discard write data */ while (towrite) { + ssize_t space = towrite; if (!is_echo) { + IO_STATUS_BLOCK iosb = {{0}, 0}; + FILE_PIPE_LOCAL_INFORMATION fpli = {0}; + NTSTATUS status; + + status = NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli), + FilePipeLocalInformation); + if (!NT_SUCCESS (status)) + { + if (towrite < len) + break; + len = -1; + return FALSE; + } if (ttyp->output_stopped && is_nonblocking) { if (towrite < len) @@ -3131,13 +3145,18 @@ fhandler_pty_common::process_opost_output (HANDLE h, const void *ptr, return TRUE; } } - while (ttyp->output_stopped) - cygwait (10); + if (ttyp->output_stopped || fpli.WriteQuotaAvailable == 0) + { + cygwait (1); + continue; + } + space = fpli.WriteQuotaAvailable; } if (!(ttyp->ti.c_oflag & OPOST)) // raw output mode { DWORD n = MIN (OUT_BUFFER_SIZE, towrite); + n = MIN (n, space); res = WriteFile (h, ptr, n, &n, NULL); if (!res) break; @@ -3150,7 +3169,7 @@ fhandler_pty_common::process_opost_output (HANDLE h, const void *ptr, char *buf = (char *)ptr; DWORD n = 0; ssize_t rc = 0; - while (n < OUT_BUFFER_SIZE && rc < towrite) + while (n < OUT_BUFFER_SIZE && n < space && rc < towrite) { switch (buf[rc]) { diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h index 87adca9..3d819f4 100644 --- a/winsup/cygwin/local_includes/fhandler.h +++ b/winsup/cygwin/local_includes/fhandler.h @@ -2180,10 +2180,6 @@ class dev_console friend class fhandler_console; }; -#define MAX_CONS_DEV (sizeof (unsigned long) * 8) -#define CONS_SCAN_UNUSED (-1) -#define CONS_LIST_USED (-2) - /* This is a input and output console handle */ class fhandler_console: public fhandler_termios { @@ -2376,13 +2372,10 @@ private: class console_unit { int n; - unsigned long bitmask; - console_state *shared_console_info; public: - operator console_state * () const {return shared_console_info;} - operator unsigned long () const {return n == CONS_LIST_USED ? bitmask : n;} - console_unit (int); - friend BOOL CALLBACK fhandler_console::enum_windows (HWND, LPARAM); + operator console_state * () const; + operator int () const { return n; } + console_unit (int, HANDLE *input_mutex = NULL); }; friend tty_min * tty_list::get_cttyp (); @@ -2870,11 +2863,12 @@ class fhandler_dev_dsp: public fhandler_base int close (); void fixup_after_fork (HANDLE); void fixup_after_exec (); + bool open_setup (int); private: - ssize_t _write (const void *, size_t); - void _read (void *, size_t&); - int _ioctl (unsigned int, void *); + ssize_t _write (const void *, size_t, fhandler_dev_dsp *); + void _read (void *, size_t&, fhandler_dev_dsp *); + int _ioctl (unsigned int, void *, fhandler_dev_dsp *); int _fcntl (int cmd, intptr_t); void _fixup_after_fork (HANDLE); void _fixup_after_exec (); diff --git a/winsup/cygwin/local_includes/shared_info.h b/winsup/cygwin/local_includes/shared_info.h index cbe55a2..4316717 100644 --- a/winsup/cygwin/local_includes/shared_info.h +++ b/winsup/cygwin/local_includes/shared_info.h @@ -33,7 +33,7 @@ public: /* Data accessible to all tasks */ -#define CURR_SHARED_MAGIC 0x9f33cc5dU +#define CURR_SHARED_MAGIC 0x205f4579U #define USER_VERSION 1 @@ -46,6 +46,7 @@ class shared_info DWORD cb; public: tty_list tty; + HWND cons_hwnd[MAX_CONS_DEV]; LONG last_used_bindresvport; DWORD obcaseinsensitive; mtinfo mt; diff --git a/winsup/cygwin/local_includes/tty.h b/winsup/cygwin/local_includes/tty.h index df3bf60..53fa26b 100644 --- a/winsup/cygwin/local_includes/tty.h +++ b/winsup/cygwin/local_includes/tty.h @@ -211,4 +211,9 @@ public: }; extern "C" int ttyslot (void); + +/* Console stuff */ +#define MAX_CONS_DEV 128 +#define CONS_SCAN_UNUSED (-1) + #endif /*_TTY_H*/ diff --git a/winsup/cygwin/release/3.5.4 b/winsup/cygwin/release/3.5.4 index 2a5f2b1..c95ef46 100644 --- a/winsup/cygwin/release/3.5.4 +++ b/winsup/cygwin/release/3.5.4 @@ -15,3 +15,10 @@ Fixes: - Fix a problem that ldd command against cygwin DLLs sometimes hangs. Addresses: https://cygwin.com/pipermail/cygwin/2024-May/255991.html + +- Fix a problem that pty slave hangs on writing when pty master stops + to read. + Addresses: https://cygwin.com/pipermail/cygwin/2024-June/256178.html + +- Fix conflict on shared name in console between sessions. + Addresses: https://cygwin.com/pipermail/cygwin/2024-April/255893.html |