aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--winsup/cygwin/devices.cc4
-rw-r--r--winsup/cygwin/devices.in4
-rw-r--r--winsup/cygwin/exceptions.cc3
-rw-r--r--winsup/cygwin/fhandler/console.cc162
-rw-r--r--winsup/cygwin/fhandler/dsp.cc26
-rw-r--r--winsup/cygwin/fhandler/pty.cc25
-rw-r--r--winsup/cygwin/local_includes/fhandler.h20
-rw-r--r--winsup/cygwin/local_includes/shared_info.h3
-rw-r--r--winsup/cygwin/local_includes/tty.h5
-rw-r--r--winsup/cygwin/release/3.5.47
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