aboutsummaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/devices.cc4
-rw-r--r--winsup/cygwin/devices.in4
-rw-r--r--winsup/cygwin/exceptions.cc5
-rw-r--r--winsup/cygwin/fhandler/console.cc314
-rw-r--r--winsup/cygwin/fhandler/disk_file.cc3
-rw-r--r--winsup/cygwin/fhandler/dsp.cc26
-rw-r--r--winsup/cygwin/fhandler/fifo.cc2
-rw-r--r--winsup/cygwin/fhandler/pipe.cc103
-rw-r--r--winsup/cygwin/fhandler/proc.cc3
-rw-r--r--winsup/cygwin/fhandler/pty.cc105
-rw-r--r--winsup/cygwin/fhandler/socket.cc2
-rw-r--r--winsup/cygwin/fhandler/tape.cc4
-rw-r--r--winsup/cygwin/fhandler/termios.cc78
-rw-r--r--winsup/cygwin/flock.cc89
-rw-r--r--winsup/cygwin/include/asm/socket.h4
-rw-r--r--winsup/cygwin/include/cygwin/version.h2
-rw-r--r--winsup/cygwin/include/getopt.h2
-rw-r--r--winsup/cygwin/include/pthread.h13
-rw-r--r--winsup/cygwin/local_includes/fhandler.h48
-rw-r--r--winsup/cygwin/local_includes/mtinfo.h2
-rw-r--r--winsup/cygwin/local_includes/ntdll.h2
-rw-r--r--winsup/cygwin/local_includes/select.h5
-rw-r--r--winsup/cygwin/local_includes/shared_info.h3
-rw-r--r--winsup/cygwin/local_includes/tty.h6
-rw-r--r--winsup/cygwin/local_includes/winlean.h3
-rw-r--r--winsup/cygwin/net.cc2
-rw-r--r--winsup/cygwin/nlsfuncs.cc95
-rw-r--r--winsup/cygwin/pinfo.cc2
-rw-r--r--winsup/cygwin/posix_timer.cc1
-rw-r--r--winsup/cygwin/release/3.5.413
-rw-r--r--winsup/cygwin/release/3.5.535
-rwxr-xr-xwinsup/cygwin/scripts/gendef15
-rw-r--r--winsup/cygwin/select.cc56
-rw-r--r--winsup/cygwin/sigproc.cc11
-rw-r--r--winsup/cygwin/spawn.cc1
-rw-r--r--winsup/cygwin/thread.cc8
-rw-r--r--winsup/cygwin/tty.cc2
-rw-r--r--winsup/utils/kill.cc2
38 files changed, 729 insertions, 346 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..3195d57 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -665,7 +665,7 @@ exception::handle (EXCEPTION_RECORD *e, exception_list *frame, CONTEXT *in,
siginfo_t si = {};
si.si_code = SI_KERNEL;
/* Coerce win32 value to posix value. */
- switch (e->ExceptionCode)
+ switch ((NTSTATUS) e->ExceptionCode)
{
case STATUS_FLOAT_DIVIDE_BY_ZERO:
si.si_signo = SIGFPE;
@@ -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..2651e49 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;
@@ -56,6 +60,10 @@ const unsigned fhandler_console::MAX_WRITE_CHARS = 16384;
fhandler_console::console_state NO_COPY
*fhandler_console::shared_console_info[MAX_CONS_DEV + 1];
+static bool NO_COPY inside_pcon_checked = false;
+static bool NO_COPY inside_pcon = false;
+static int NO_COPY parent_pty;
+
bool NO_COPY fhandler_console::invisible_console;
/* con_ra is shared in the same process.
@@ -67,37 +75,33 @@ static struct fhandler_base::rabuf_t con_ra;
static wchar_t last_char;
DWORD
-fhandler_console::attach_console (pid_t owner, bool *err)
+fhandler_console::attach_console (DWORD owner, bool *err)
{
DWORD resume_pid = (DWORD) -1;
- pinfo p (owner);
- if (p)
+ if (!process_alive (owner))
+ return resume_pid;
+ DWORD attached =
+ get_console_process_id (owner, true, false, false);
+ if (!attached)
{
- DWORD attached =
- fhandler_pty_common::get_console_process_id (p->dwProcessId,
- true, false, false);
- if (!attached)
+ resume_pid =
+ get_console_process_id (GetCurrentProcessId (), false, false, false);
+ FreeConsole ();
+ BOOL r = AttachConsole (owner);
+ if (!r)
{
- resume_pid =
- fhandler_pty_common::get_console_process_id (myself->dwProcessId,
- false, false, false);
- FreeConsole ();
- BOOL r = AttachConsole (p->dwProcessId);
- if (!r)
- {
- if (resume_pid)
- AttachConsole (resume_pid);
- if (err)
- *err = true;
- return (DWORD) -1;
- }
+ if (resume_pid)
+ AttachConsole (resume_pid);
+ if (err)
+ *err = true;
+ return (DWORD) -1;
}
}
return resume_pid;
}
void
-fhandler_console::detach_console (DWORD resume_pid, pid_t owner)
+fhandler_console::detach_console (DWORD resume_pid, DWORD owner)
{
if (resume_pid == (DWORD) -1)
return;
@@ -106,11 +110,11 @@ fhandler_console::detach_console (DWORD resume_pid, pid_t owner)
FreeConsole ();
AttachConsole (resume_pid);
}
- else if (myself->pid != owner)
+ else if (GetCurrentProcessId () != owner)
FreeConsole ();
}
-pid_t
+DWORD
fhandler_console::get_owner ()
{
return con.owner;
@@ -129,14 +133,14 @@ public:
{
empty ();
}
- inline void put (HANDLE output_handle, pid_t owner, char x)
+ inline void put (HANDLE output_handle, DWORD owner, char x)
{
if (ixput == WPBUF_LEN)
send (output_handle, owner);
buf[ixput++] = x;
}
inline void empty () { ixput = 0u; }
- inline void send (HANDLE output_handle, pid_t owner)
+ inline void send (HANDLE output_handle, DWORD owner)
{
if (!output_handle)
{
@@ -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;
}
@@ -377,7 +395,7 @@ fhandler_console::cons_master_thread (handle_set_t *p, tty *ttyp)
}
};
termios &ti = ttyp->ti;
- while (con.owner == myself->pid)
+ while (con.owner == GetCurrentProcessId ())
{
DWORD total_read, n, i;
@@ -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,20 +697,24 @@ 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
unit = device::minor (cs->tty_min_state.ntty);
shared_console_info[unit] = cs;
if (created)
- con.owner = myself->pid;
+ con.owner = GetCurrentProcessId ();
}
}
}
+ ReleaseMutex (shared_info_mutex);
+
if (shared_console_info[unit])
{
devset = (fh_devices) shared_console_info[unit]->tty_min_state.getntty ();
@@ -786,6 +818,7 @@ fhandler_console::set_input_mode (tty::cons_mode m, const termios *t,
GetConsoleMode (p->input_handle, &oflags);
DWORD flags = oflags
& (ENABLE_EXTENDED_FLAGS | ENABLE_INSERT_MODE | ENABLE_QUICK_EDIT_MODE);
+ con.curr_input_mode = m;
switch (m)
{
case tty::restore:
@@ -835,6 +868,7 @@ fhandler_console::set_output_mode (tty::cons_mode m, const termios *t,
if (con.orig_virtual_terminal_processing_mode)
flags |= ENABLE_VIRTUAL_TERMINAL_PROCESSING;
WaitForSingleObject (p->output_mutex, mutex_timeout);
+ con.curr_output_mode = m;
switch (m)
{
case tty::restore:
@@ -883,10 +917,10 @@ fhandler_console::cleanup_for_non_cygwin_app (handle_set_t *p)
/* conmode can be tty::restore when non-cygwin app is
exec'ed from login shell. */
tty::cons_mode conmode =
- (con.owner == myself->pid) ? tty::restore : tty::cygwin;
+ (con.owner == GetCurrentProcessId ()) ? tty::restore : tty::cygwin;
set_output_mode (conmode, ti, p);
set_input_mode (conmode, ti, p);
- set_disable_master_thread (con.owner == myself->pid);
+ set_disable_master_thread (con.owner == GetCurrentProcessId ());
}
/* Return the tty structure associated with a given tty number. If the
@@ -999,7 +1033,7 @@ fhandler_console::set_cursor_maybe ()
/* Workaround for a bug of windows xterm compatible mode. */
/* The horizontal tab positions are broken after resize. */
void
-fhandler_console::fix_tab_position (HANDLE h, pid_t owner)
+fhandler_console::fix_tab_position (HANDLE h, DWORD owner)
{
/* Re-setting ENABLE_VIRTUAL_TERMINAL_PROCESSING
fixes the tab position. */
@@ -1077,12 +1111,12 @@ fhandler_console::bg_check (int sig, bool dontsignal)
/* Setting-up console mode for cygwin app. This is necessary if the
cygwin app and other non-cygwin apps are started simultaneously
in the same process group. */
- if (sig == SIGTTIN)
+ if (sig == SIGTTIN && con.curr_input_mode != tty::cygwin)
{
set_input_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
set_disable_master_thread (false, this);
}
- if (sig == SIGTTOU)
+ if (sig == SIGTTOU && con.curr_output_mode != tty::cygwin)
set_output_mode (tty::cygwin, &tc ()->ti, get_handle_set ());
return fhandler_termios::bg_check (sig, dontsignal);
@@ -1739,13 +1773,8 @@ fhandler_console::open (int flags, mode_t)
setup_io_mutex ();
acquire_output_mutex (mutex_timeout);
- do
- {
- pinfo p (con.owner);
- if (!p)
- con.owner = myself->pid;
- }
- while (false);
+ if (!process_alive (con.owner))
+ con.owner = GetCurrentProcessId ();
/* Open the input handle as handle_ */
bool err = false;
@@ -1809,7 +1838,7 @@ fhandler_console::open (int flags, mode_t)
set_open_status ();
- if (myself->pid == con.owner && wincap.has_con_24bit_colors ())
+ if (GetCurrentProcessId () == con.owner && wincap.has_con_24bit_colors ())
{
bool is_legacy = false;
DWORD dwMode;
@@ -1840,26 +1869,88 @@ fhandler_console::open (int flags, mode_t)
debug_printf ("opened conin$ %p, conout$ %p", get_handle (),
get_output_handle ());
- if (myself->pid == con.owner)
+ if (GetCurrentProcessId () == con.owner)
{
if (GetModuleHandle ("ConEmuHk64.dll"))
hook_conemu_cygwin_connector ();
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;
}
+void
+fhandler_console::setup_pcon_hand_over ()
+{
+ /* Prepare for pcon hand over */
+ if (!inside_pcon_checked)
+ for (int i = 0; i < NTTYS; i++)
+ {
+ if (!cygwin_shared->tty[i]->pcon_activated)
+ continue;
+ DWORD owner = cygwin_shared->tty[i]->nat_pipe_owner_pid;
+ if (get_console_process_id (owner, true, false, false, false))
+ {
+ inside_pcon = true;
+ atexit (fhandler_console::pcon_hand_over_proc);
+ parent_pty = i;
+ break;
+ }
+ }
+ inside_pcon_checked = true;
+}
+
+void
+fhandler_console::pcon_hand_over_proc (void)
+{
+ if (!inside_pcon)
+ return;
+ tty *ttyp = cygwin_shared->tty[parent_pty];
+ char buf[MAX_PATH];
+ shared_name (buf, PIPE_SW_MUTEX, parent_pty);
+ HANDLE mtx = OpenMutex (MAXIMUM_ALLOWED, FALSE, buf);
+ WaitForSingleObject (mtx, INFINITE);
+ ReleaseMutex (mtx);
+ DWORD res = WaitForSingleObject (mtx, INFINITE);
+ if (res == WAIT_OBJECT_0 || res == WAIT_ABANDONED)
+ {
+ DWORD owner = ttyp->nat_pipe_owner_pid;
+ if (owner == GetCurrentProcessId ()
+ || owner == (myself->exec_dwProcessId ?: myself->dwProcessId))
+ fhandler_pty_slave::close_pseudoconsole (ttyp, 0);
+ }
+ else
+ system_printf("Acquiring pcon_ho_mutex failed.");
+ /* Do not release the mutex.
+ Hold onto the mutex until this process completes. */
+}
+
bool
fhandler_console::open_setup (int flags)
{
set_flags ((flags & ~O_TEXT) | O_BINARY);
if (myself->set_ctty (this, flags) && !myself->cygstarted)
- init_console_handler (true);
+ {
+ init_console_handler (true);
+ setup_pcon_hand_over ();
+
+ /* Initialize handle_set */
+ handle_set.input_handle = get_handle ();
+ handle_set.output_handle = get_output_handle ();
+ handle_set.input_mutex = input_mutex;
+ handle_set.output_mutex = output_mutex;
+ handle_set.unit = unit;
+ }
return fhandler_base::open_setup (flags);
}
@@ -1885,16 +1976,16 @@ fhandler_console::close ()
acquire_output_mutex (mutex_timeout);
- if (shared_console_info[unit])
+ if (shared_console_info[unit] && !myself->cygstarted
+ && (dev_t) myself->ctty == get_device ())
{
/* Restore console mode if this is the last closure. */
OBJECT_BASIC_INFORMATION obi;
NTSTATUS status;
status = NtQueryObject (get_handle (), ObjectBasicInformation,
&obi, sizeof obi, NULL);
- if ((NT_SUCCESS (status) && obi.HandleCount == 1
- && (dev_t) myself->ctty == get_device ())
- || myself->pid == con.owner)
+ if (NT_SUCCESS (status)
+ && obi.HandleCount == (con.owner == GetCurrentProcessId () ? 2 : 3))
{
/* Cleaning-up console mode for cygwin apps. */
set_output_mode (tty::restore, &get_ttyp ()->ti, &handle_set);
@@ -1903,16 +1994,22 @@ fhandler_console::close ()
}
}
- if (shared_console_info[unit] && con.owner == myself->pid)
+ if (shared_console_info[unit] && con.owner == GetCurrentProcessId ())
{
if (master_thread_started)
{
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 = (DWORD) -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 +2024,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 +2049,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;
}
@@ -2859,6 +2974,8 @@ fhandler_console::char_command (char c)
}
if (con.args[i] == 1) /* DECCKM */
con.cursor_key_app_mode = (c == 'h');
+ if (con.args[i] == 9001) /* win32-input-mode (https://github.com/microsoft/terminal/blob/main/doc/specs/%234999%20-%20Improved%20keyboard%20handling%20in%20Conpty.md) */
+ set_disable_master_thread (c == 'h', this);
}
/* Call fix_tab_position() if screen has been alternated. */
if (need_fix_tab_position)
@@ -3375,7 +3492,7 @@ enum_proc (const LOGFONTW *lf, const TEXTMETRICW *tm,
}
static void
-check_font (HANDLE hdl, pid_t owner)
+check_font (HANDLE hdl, DWORD owner)
{
CONSOLE_FONT_INFOEX cfi;
LOGFONTW lf;
@@ -4261,6 +4378,7 @@ fhandler_console::fixup_after_fork_exec (bool execing)
cygheap->ctty = NULL;
return;
}
+ setup_pcon_hand_over ();
if (!execing)
return;
diff --git a/winsup/cygwin/fhandler/disk_file.cc b/winsup/cygwin/fhandler/disk_file.cc
index 2cfac6b..794c8eb 100644
--- a/winsup/cygwin/fhandler/disk_file.cc
+++ b/winsup/cygwin/fhandler/disk_file.cc
@@ -1810,6 +1810,9 @@ fhandler_disk_file::prw_open (bool write, void *aio)
return -1;
}
+ /* prw_handle is invalid after fork. */
+ need_fork_fixup (true);
+
/* record prw_handle's asyncness for subsequent pread/pwrite operations */
prw_handle_isasync = !!aio;
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/fifo.cc b/winsup/cygwin/fhandler/fifo.cc
index efea508..ee49ce6 100644
--- a/winsup/cygwin/fhandler/fifo.cc
+++ b/winsup/cygwin/fhandler/fifo.cc
@@ -669,7 +669,7 @@ fhandler_fifo::create_shmem (bool only_open)
{
HANDLE sect;
OBJECT_ATTRIBUTES attr;
- NTSTATUS status;
+ NTSTATUS status = STATUS_SUCCESS;
LARGE_INTEGER size = { .QuadPart = sizeof (fifo_shmem_t) };
SIZE_T viewsize = sizeof (fifo_shmem_t);
PVOID addr = NULL;
diff --git a/winsup/cygwin/fhandler/pipe.cc b/winsup/cygwin/fhandler/pipe.cc
index 4c4ad03..6a1ef03 100644
--- a/winsup/cygwin/fhandler/pipe.cc
+++ b/winsup/cygwin/fhandler/pipe.cc
@@ -13,6 +13,7 @@ details. */
#include "security.h"
#include "path.h"
#include "fhandler.h"
+#include "select.h"
#include "dtable.h"
#include "cygheap.h"
#include "pinfo.h"
@@ -53,6 +54,16 @@ fhandler_pipe::set_pipe_non_blocking (bool nonblocking)
NTSTATUS status;
IO_STATUS_BLOCK io;
FILE_PIPE_INFORMATION fpi;
+ bool was_blocking_read_pipe_new = was_blocking_read_pipe;
+
+ if (get_device () == FH_PIPER && nonblocking && !was_blocking_read_pipe)
+ {
+ status = NtQueryInformationFile (get_handle (), &io, &fpi, sizeof fpi,
+ FilePipeInformation);
+ if (NT_SUCCESS (status))
+ was_blocking_read_pipe_new =
+ (fpi.CompletionMode == FILE_PIPE_QUEUE_OPERATION);
+ }
fpi.ReadMode = FILE_PIPE_BYTE_STREAM_MODE;
fpi.CompletionMode = nonblocking ? FILE_PIPE_COMPLETE_OPERATION
@@ -61,6 +72,11 @@ fhandler_pipe::set_pipe_non_blocking (bool nonblocking)
FilePipeInformation);
if (!NT_SUCCESS (status))
debug_printf ("NtSetInformationFile(FilePipeInformation): %y", status);
+ else
+ {
+ was_blocking_read_pipe = was_blocking_read_pipe_new;
+ is_blocking_read_pipe = !nonblocking;
+ }
}
int
@@ -94,6 +110,8 @@ fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode, int64_t uniq_id)
even with FILE_SYNCHRONOUS_IO_NONALERT. */
set_pipe_non_blocking (get_device () == FH_PIPER ?
true : is_nonblocking ());
+ was_blocking_read_pipe = false;
+
return 1;
}
@@ -288,6 +306,9 @@ fhandler_pipe::raw_read (void *ptr, size_t& len)
if (!len)
return;
+ if (is_blocking_read_pipe)
+ set_pipe_non_blocking (true);
+
DWORD timeout = is_nonblocking () ? 0 : INFINITE;
DWORD waitret = cygwait (read_mtx, timeout);
switch (waitret)
@@ -418,6 +439,7 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
NTSTATUS status = STATUS_SUCCESS;
IO_STATUS_BLOCK io;
HANDLE evt;
+ bool short_write_once = false;
if (!len)
return 0;
@@ -456,6 +478,7 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
len1 = chunk;
else
len1 = (ULONG) left;
+
/* NtWriteFile returns success with # of bytes written == 0 if writing
on a non-blocking pipe fails because the pipe buffer doesn't have
sufficient space.
@@ -483,9 +506,16 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
(PVOID) ptr, len1, NULL, NULL);
if (status == STATUS_PENDING)
{
- while (WAIT_TIMEOUT ==
- (waitret = cygwait (evt, (DWORD) 0, cw_cancel | cw_sig)))
+ do
{
+ /* To allow constant reader_closed() checking even if the
+ signal has been set up with SA_RESTART, we're handling
+ the signal here --> cw_sig_eintr. */
+ waitret = cygwait (evt, (DWORD) 0, cw_cancel | cw_sig_eintr);
+ /* Break out if no SA_RESTART. */
+ if (waitret == WAIT_SIGNALED
+ && !_my_tls.call_signal_handler ())
+ break;
if (reader_closed ())
{
CancelIo (get_handle ());
@@ -493,9 +523,20 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
raise (SIGPIPE);
goto out;
}
- else
- cygwait (select_sem, 10);
+ /* Break out on completion */
+ if (waitret == WAIT_OBJECT_0)
+ break;
+ /* If we got a timeout in the blocking case, and we already
+ did a short write, we got a signal in the previous loop. */
+ if (waitret == WAIT_TIMEOUT && short_write_once)
+ {
+ waitret = WAIT_SIGNALED;
+ break;
+ }
+ cygwait (select_sem, 10, cw_cancel);
}
+ /* Loop in case of blocking write or SA_RESTART */
+ while (waitret == WAIT_TIMEOUT || waitret == WAIT_SIGNALED);
/* If io.Status is STATUS_CANCELLED after CancelIo, IO has
actually been cancelled and io.Information contains the
number of bytes processed so far.
@@ -509,13 +550,38 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
status = STATUS_THREAD_CANCELED;
else if (waitret == WAIT_SIGNALED)
status = STATUS_THREAD_SIGNALED;
+ else if (waitret == WAIT_TIMEOUT && io.Status == STATUS_CANCELLED)
+ status = STATUS_SUCCESS;
else
status = io.Status;
}
- if (!is_nonblocking () || !NT_SUCCESS (status) || io.Information > 0
- || len <= PIPE_BUF)
+ if (status != STATUS_THREAD_SIGNALED && !NT_SUCCESS (status))
+ break;
+ if (io.Information > 0 || len <= PIPE_BUF || short_write_once)
break;
- len1 >>= 1;
+ /* Independent of being blocking or non-blocking, if we're here,
+ the pipe has less space than requested. If the pipe is a
+ non-Cygwin pipe, just try the old strategy of trying a half
+ write. If the pipe has at
+ least PIPE_BUF bytes available, try to write all matching
+ PIPE_BUF sized blocks. If it's less than PIPE_BUF, try
+ the next less power of 2 bytes. This is not really the Linux
+ strategy because Linux is filling the pages of a pipe buffer
+ in a very implementation-defined way we can't emulate, but it
+ resembles it closely enough to get useful results. */
+ ssize_t avail = pipe_data_available (-1, this, get_handle (),
+ PDA_WRITE);
+ if (avail < 1) /* error or pipe closed */
+ break;
+ if (avail > len1) /* somebody read from the pipe */
+ avail = len1;
+ if (avail == 1) /* 1 byte left or non-Cygwin pipe */
+ len1 >>= 1;
+ else if (avail >= PIPE_BUF)
+ len1 = avail & ~(PIPE_BUF - 1);
+ else
+ len1 = 1 << (63 - __builtin_clzl (avail));
+ short_write_once = true;
}
if (isclosed ()) /* A signal handler might have closed the fd. */
{
@@ -545,7 +611,7 @@ fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
else
__seterrno_from_nt_status (status);
- if (nbytes_now == 0)
+ if (nbytes_now == 0 || short_write_once)
break;
}
out:
@@ -675,6 +741,8 @@ fhandler_pipe::close ()
CloseHandle (query_hdl);
if (query_hdl_close_req_evt)
CloseHandle (query_hdl_close_req_evt);
+ if (was_blocking_read_pipe)
+ set_pipe_non_blocking (false);
int ret = fhandler_base::close ();
ReleaseMutex (hdl_cnt_mtx);
CloseHandle (hdl_cnt_mtx);
@@ -1327,6 +1395,7 @@ fhandler_pipe::spawn_worker (int fileno_stdin, int fileno_stdout,
{
fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
pipe->set_pipe_non_blocking (false);
+ need_send_noncygchld_sig = true;
}
/* If multiple writers including non-cygwin app exist, the non-cygwin
@@ -1352,3 +1421,21 @@ fhandler_pipe::spawn_worker (int fileno_stdin, int fileno_stdout,
t->kill_pgrp (__SIGNONCYGCHLD);
}
}
+
+void
+fhandler_pipe::sigproc_worker (void)
+{
+ cygheap_fdenum cfd (false);
+ while (cfd.next () >= 0)
+ if (cfd->get_dev () == FH_PIPEW)
+ {
+ fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
+ if (pipe->need_close_query_hdl ())
+ pipe->close_query_handle ();
+ }
+ else if (cfd->get_dev () == FH_PIPER)
+ {
+ fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
+ pipe->is_blocking_read_pipe = true;
+ }
+}
diff --git a/winsup/cygwin/fhandler/proc.cc b/winsup/cygwin/fhandler/proc.cc
index be107cb..fcd6441 100644
--- a/winsup/cygwin/fhandler/proc.cc
+++ b/winsup/cygwin/fhandler/proc.cc
@@ -2153,8 +2153,7 @@ format_proc_locale_proc (LPWSTR win_locale, DWORD info, LPARAM param)
if (!(cp2 = wcschr (cp + 2, L'-')))
return TRUE;
/* Otherwise, store in iso15924 */
- if (iso15924)
- wcpcpy (wcpncpy (iso15924, cp, cp2 - cp), L";");
+ wcpcpy (wcpncpy (iso15924, cp, cp2 - cp), L";");
}
cp = wcsrchr (win_locale, L'-');
if (cp)
diff --git a/winsup/cygwin/fhandler/pty.cc b/winsup/cygwin/fhandler/pty.cc
index 9d7ef3c..4f0f718 100644
--- a/winsup/cygwin/fhandler/pty.cc
+++ b/winsup/cygwin/fhandler/pty.cc
@@ -74,58 +74,6 @@ void release_attach_mutex (void)
ReleaseMutex (attach_mutex);
}
-inline static bool process_alive (DWORD pid);
-
-/* This functions looks for a process which attached to the same console
- with current process and is matched to given conditions:
- match: If true, return given pid if the process pid attaches to the
- same console, otherwise, return 0. If false, return pid except
- for given pid.
- cygwin: return only process's pid which has cygwin pid.
- stub_only: return only stub process's pid of non-cygwin process. */
-DWORD
-fhandler_pty_common::get_console_process_id (DWORD pid, bool match,
- bool cygwin, bool stub_only,
- bool nat)
-{
- tmp_pathbuf tp;
- DWORD *list = (DWORD *) tp.c_get ();
- const DWORD buf_size = NT_MAX_PATH / sizeof (DWORD);
-
- DWORD num = GetConsoleProcessList (list, buf_size);
- if (num == 0 || num > buf_size)
- return 0;
-
- DWORD res_pri = 0, res = 0;
- /* Last one is the oldest. */
- /* https://github.com/microsoft/terminal/issues/95 */
- for (int i = (int) num - 1; i >= 0; i--)
- if ((match && list[i] == pid) || (!match && list[i] != pid))
- {
- if (!cygwin)
- {
- res_pri = list[i];
- break;
- }
- else
- {
- pinfo p (cygwin_pid (list[i]));
- if (nat && !!p && !ISSTATE(p, PID_NOTCYGWIN))
- continue;
- if (!!p && p->exec_dwProcessId)
- {
- res_pri = stub_only ? p->exec_dwProcessId : list[i];
- break;
- }
- if (!p && !res && process_alive (list[i]) && stub_only)
- res = list[i];
- if (!!p && !res && !stub_only)
- res = list[i];
- }
- }
- return res_pri ?: res;
-}
-
static bool isHybrid; /* Set true if the active pipe is set to nat pipe
owned by myself even though the current process
is a cygwin process. */
@@ -1113,27 +1061,10 @@ fhandler_pty_slave::set_switch_to_nat_pipe (void)
}
inline static bool
-process_alive (DWORD pid)
-{
- /* This function is very similar to _pinfo::alive(), however, this
- can be used for non-cygwin process which is started from non-cygwin
- shell. In addition, this checks exit code as well. */
- if (pid == 0)
- return false;
- HANDLE h = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
- if (h == NULL)
- return false;
- DWORD exit_code;
- BOOL r = GetExitCodeProcess (h, &exit_code);
- CloseHandle (h);
- if (r && exit_code == STILL_ACTIVE)
- return true;
- return false;
-}
-
-inline static bool
nat_pipe_owner_self (DWORD pid)
{
+ if (pid == GetCurrentProcessId ())
+ return true;
return (pid == (myself->exec_dwProcessId ?: myself->dwProcessId));
}
@@ -3118,8 +3049,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 +3076,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 +3100,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])
{
@@ -3522,11 +3472,16 @@ fhandler_pty_slave::get_winpid_to_hand_over (tty *ttyp,
{
/* Search another native process which attaches to the same console */
DWORD current_pid = myself->exec_dwProcessId ?: myself->dwProcessId;
+ if (ttyp->nat_pipe_owner_pid == GetCurrentProcessId ())
+ current_pid = GetCurrentProcessId ();
switch_to = get_console_process_id (current_pid,
false, true, true, true);
if (!switch_to)
switch_to = get_console_process_id (current_pid,
false, true, false, true);
+ if (!switch_to)
+ switch_to = get_console_process_id (current_pid,
+ false, false, false, false);
}
return switch_to;
}
@@ -3554,13 +3509,13 @@ fhandler_pty_slave::hand_over_only (tty *ttyp, DWORD force_switch_to)
void
fhandler_pty_slave::close_pseudoconsole (tty *ttyp, DWORD force_switch_to)
{
- DWORD switch_to = get_winpid_to_hand_over (ttyp, force_switch_to);
acquire_attach_mutex (mutex_timeout);
ttyp->previous_code_page = GetConsoleCP ();
ttyp->previous_output_code_page = GetConsoleOutputCP ();
release_attach_mutex ();
if (nat_pipe_owner_self (ttyp->nat_pipe_owner_pid))
{ /* I am owner of the nat pipe. */
+ DWORD switch_to = get_winpid_to_hand_over (ttyp, force_switch_to);
if (switch_to)
{
/* Change pseudo console owner to another process (switch_to). */
diff --git a/winsup/cygwin/fhandler/socket.cc b/winsup/cygwin/fhandler/socket.cc
index f7c5ff6..c0cef7d 100644
--- a/winsup/cygwin/fhandler/socket.cc
+++ b/winsup/cygwin/fhandler/socket.cc
@@ -86,7 +86,7 @@ struct __old_ifreq {
int
fhandler_socket::ioctl (unsigned int cmd, void *p)
{
- extern int get_ifconf (struct ifconf *ifc, int what); /* net.cc */
+ extern int get_ifconf (struct ifconf *ifc, unsigned int what); /* net.cc */
int res;
struct ifconf ifc, *ifcp;
struct ifreq *ifrp;
diff --git a/winsup/cygwin/fhandler/tape.cc b/winsup/cygwin/fhandler/tape.cc
index 0e235f1..732fd1b 100644
--- a/winsup/cygwin/fhandler/tape.cc
+++ b/winsup/cygwin/fhandler/tape.cc
@@ -894,9 +894,9 @@ mtinfo_drive::get_status (HANDLE mt, struct mtget *get)
}
int
-mtinfo_drive::set_options (HANDLE mt, int32_t options)
+mtinfo_drive::set_options (HANDLE mt, uint32_t options)
{
- int32_t what = (options & MT_ST_OPTIONS);
+ uint32_t what = (options & MT_ST_OPTIONS);
bool call_setparams = false;
bool set;
TAPE_SET_DRIVE_PARAMETERS sdp =
diff --git a/winsup/cygwin/fhandler/termios.cc b/winsup/cygwin/fhandler/termios.cc
index d106955..585e6ac 100644
--- a/winsup/cygwin/fhandler/termios.cc
+++ b/winsup/cygwin/fhandler/termios.cc
@@ -20,6 +20,7 @@ details. */
#include "cygheap.h"
#include "child_info.h"
#include "ntdll.h"
+#include "tls_pbuf.h"
/* Wait time for some treminal mutexes. This is set to 0 when the
process calls CreateProcess() with DEBUG_PROCESS flag, because
@@ -827,3 +828,80 @@ fhandler_termios::spawn_worker::close_handle_set ()
if (cons_need_cleanup)
fhandler_console::close_handle_set (&cons_handle_set);
}
+
+void
+fhandler_termios::atexit_func ()
+{
+ fhandler_console::pcon_hand_over_proc ();
+}
+
+bool
+fhandler_termios::process_alive (DWORD pid)
+{
+ /* This function is very similar to _pinfo::alive(), however, this
+ can be used for non-cygwin process which is started from non-cygwin
+ shell. In addition, this checks exit code as well. */
+ if (pid == 0)
+ return false;
+ HANDLE h = OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
+ if (h == NULL)
+ return false;
+ DWORD exit_code;
+ BOOL r = GetExitCodeProcess (h, &exit_code);
+ CloseHandle (h);
+ if (r && exit_code == STILL_ACTIVE)
+ return true;
+ return false;
+}
+
+/* This functions looks for a process which attached to the same console
+ with current process and is matched to given conditions:
+ match: If true, return given pid if the process pid attaches to the
+ same console, otherwise, return 0. If false, return pid except
+ for given pid.
+ cygwin: return only process's pid which has cygwin pid.
+ stub_only: return only stub process's pid of non-cygwin process. */
+DWORD
+fhandler_termios::get_console_process_id (DWORD pid, bool match,
+ bool cygwin, bool stub_only,
+ bool nat)
+{
+ tmp_pathbuf tp;
+ DWORD *list = (DWORD *) tp.c_get ();
+ const DWORD buf_size = NT_MAX_PATH / sizeof (DWORD);
+
+ DWORD num = GetConsoleProcessList (list, buf_size);
+ if (num == 0 || num > buf_size)
+ return 0;
+
+ DWORD res_pri = 0, res = 0;
+ /* Last one is the oldest. */
+ /* https://github.com/microsoft/terminal/issues/95 */
+ for (int i = (int) num - 1; i >= 0; i--)
+ if ((match && list[i] == pid) || (!match && list[i] != pid))
+ {
+ if (!process_alive (list[i]))
+ continue;
+ if (!cygwin)
+ {
+ res_pri = list[i];
+ break;
+ }
+ else
+ {
+ pinfo p (cygwin_pid (list[i]));
+ if (nat && !!p && !ISSTATE(p, PID_NOTCYGWIN))
+ continue;
+ if (!!p && p->exec_dwProcessId)
+ {
+ res_pri = stub_only ? p->exec_dwProcessId : list[i];
+ break;
+ }
+ if (!p && !res && stub_only)
+ res = list[i];
+ if (!!p && !res && !stub_only)
+ res = list[i];
+ }
+ }
+ return res_pri ?: res;
+}
diff --git a/winsup/cygwin/flock.cc b/winsup/cygwin/flock.cc
index 0f1efa0..3821bdd 100644
--- a/winsup/cygwin/flock.cc
+++ b/winsup/cygwin/flock.cc
@@ -297,6 +297,7 @@ class inode_t
HANDLE i_dir;
HANDLE i_mtx;
uint32_t i_cnt; /* # of threads referencing this instance. */
+ uint32_t i_lock_cnt; /* # of locks for this file */
public:
inode_t (dev_t dev, ino_t ino);
@@ -321,6 +322,8 @@ class inode_t
void unlock_and_remove_if_unused ();
lockf_t *get_all_locks_list ();
+ uint32_t get_lock_count () /* needs get_all_locks_list() */
+ { return i_lock_cnt; }
bool del_my_locks (long long id, HANDLE fhdl);
};
@@ -503,7 +506,8 @@ inode_t::get (dev_t dev, ino_t ino, bool create_if_missing, bool lock)
}
inode_t::inode_t (dev_t dev, ino_t ino)
-: i_lockf (NULL), i_all_lf (NULL), i_dev (dev), i_ino (ino), i_cnt (0L)
+: i_lockf (NULL), i_all_lf (NULL), i_dev (dev), i_ino (ino), i_cnt (0L),
+ i_lock_cnt (0)
{
HANDLE parent_dir;
WCHAR name[48];
@@ -610,17 +614,16 @@ inode_t::get_all_locks_list ()
dbi->ObjectName.Buffer[LOCK_OBJ_NAME_LEN] = L'\0';
if (!newlock.from_obj_name (this, &i_all_lf, dbi->ObjectName.Buffer))
continue;
- if (lock - i_all_lf >= MAX_LOCKF_CNT)
- {
- system_printf ("Warning, can't handle more than %d locks per file.",
- MAX_LOCKF_CNT);
- break;
- }
+ /* This should not be happen. The number of locks is limitted
+ in lf_setlock() and lf_clearlock() so that it does not
+ exceed MAX_LOCKF_CNT. */
+ assert (lock - i_all_lf < MAX_LOCKF_CNT);
if (lock > i_all_lf)
lock[-1].lf_next = lock;
new (lock++) lockf_t (newlock);
}
}
+ i_lock_cnt = lock - i_all_lf;
/* If no lock has been found, return NULL. */
if (lock == i_all_lf)
return NULL;
@@ -1190,6 +1193,12 @@ restart: /* Entry point after a restartable signal came in. */
return -1;
}
+/* The total number of locks shall not exceed MAX_LOCKF_CNT.
+ If once it exceeds, lf_fildoverlap() cannot work correctly.
+ Therefore, lf_setlock() and lf_clearlock() control the
+ total number of locks not to exceed MAX_LOCKF_CNT. When
+ they detect that the operation will cause excess, they
+ return ENOCLK. */
/*
* Set a byte-range lock.
*/
@@ -1346,14 +1355,31 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
*
* Handle any locks that overlap.
*/
+ node->get_all_locks_list (); /* Update lock count */
+ uint32_t lock_cnt = node->get_lock_count ();
+ /* lf_clearlock() sometimes increases the number of locks. Without
+ this room, the unlocking will never succeed in some situation. */
+ const uint32_t room_for_clearlock = 2;
+ const int incr[] = {1, 1, 2, 2, 3, 2};
+ int decr = 0;
+
prev = head;
block = *head;
needtolink = 1;
for (;;)
{
ovcase = lf_findoverlap (block, lock, SELF, &prev, &overlap);
+ /* Estimate the maximum increase in number of the locks that
+ can occur here. If this possibly exceeds the MAX_LOCKF_CNT,
+ return ENOLCK. */
if (ovcase)
- block = overlap->lf_next;
+ {
+ block = overlap->lf_next;
+ HANDLE ov_obj = overlap->lf_obj;
+ decr = (ov_obj && get_obj_handle_count (ov_obj) == 1) ? 1 : 0;
+ }
+ if (needtolink)
+ lock_cnt += incr[ovcase] - decr;
/*
* Six cases:
* 0) no overlap
@@ -1368,6 +1394,8 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
case 0: /* no overlap */
if (needtolink)
{
+ if (lock_cnt > MAX_LOCKF_CNT - room_for_clearlock)
+ return ENOLCK;
*prev = lock;
lock->lf_next = overlap;
lock->create_lock_obj ();
@@ -1380,6 +1408,8 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
* able to acquire it.
* Cygwin: Always wake lock.
*/
+ if (lock_cnt > MAX_LOCKF_CNT - room_for_clearlock)
+ return ENOLCK;
lf_wakelock (overlap, fhdl);
overlap->lf_type = lock->lf_type;
overlap->create_lock_obj ();
@@ -1397,6 +1427,11 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
*clean = lock;
break;
}
+ if (overlap->lf_start < lock->lf_start
+ && overlap->lf_end > lock->lf_end)
+ lock_cnt++;
+ if (lock_cnt > MAX_LOCKF_CNT - room_for_clearlock)
+ return ENOLCK;
if (overlap->lf_start == lock->lf_start)
{
*prev = lock;
@@ -1413,6 +1448,8 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
break;
case 3: /* lock contains overlap */
+ if (needtolink && lock_cnt > MAX_LOCKF_CNT - room_for_clearlock)
+ return ENOLCK;
/*
* If downgrading lock, others may be able to
* acquire it, otherwise take the list.
@@ -1440,6 +1477,8 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
/*
* Add lock after overlap on the list.
*/
+ if (lock_cnt > MAX_LOCKF_CNT - room_for_clearlock)
+ return ENOLCK;
lock->lf_next = overlap->lf_next;
overlap->lf_next = lock;
overlap->lf_end = lock->lf_start - 1;
@@ -1454,13 +1493,16 @@ lf_setlock (lockf_t *lock, inode_t *node, lockf_t **clean, HANDLE fhdl)
/*
* Add the new lock before overlap.
*/
- if (needtolink) {
+ if (needtolink)
+ {
+ if (lock_cnt > MAX_LOCKF_CNT - room_for_clearlock)
+ return ENOLCK;
*prev = lock;
lock->lf_next = overlap;
- }
+ lock->create_lock_obj ();
+ }
overlap->lf_start = lock->lf_end + 1;
lf_wakelock (overlap, fhdl);
- lock->create_lock_obj ();
overlap->create_lock_obj ();
break;
}
@@ -1482,12 +1524,35 @@ lf_clearlock (lockf_t *unlock, lockf_t **clean, HANDLE fhdl)
lockf_t *lf = *head;
lockf_t *overlap, **prev;
int ovcase;
+ inode_t *node = lf->lf_inode;
+ tmp_pathbuf tp;
+ node->i_all_lf = (lockf_t *) tp.w_get ();
+ node->get_all_locks_list (); /* Update lock count */
+ uint32_t lock_cnt = node->get_lock_count ();
+ bool first_loop = true;
if (lf == NOLOCKF)
return 0;
prev = head;
while ((ovcase = lf_findoverlap (lf, unlock, SELF, &prev, &overlap)))
{
+ /* Estimate the maximum increase in number of the locks that
+ can occur here. If this possibly exceeds the MAX_LOCKF_CNT,
+ return ENOLCK. */
+ HANDLE ov_obj = overlap->lf_obj;
+ if (first_loop)
+ {
+ const int incr[] = {0, 0, 1, 1, 2, 1};
+ int decr = (ov_obj && get_obj_handle_count (ov_obj) == 1) ? 1 : 0;
+ lock_cnt += incr[ovcase] - decr;
+ if (ovcase == 2
+ && overlap->lf_start < unlock->lf_start
+ && overlap->lf_end > unlock->lf_end)
+ lock_cnt++;
+ if (lock_cnt > MAX_LOCKF_CNT)
+ return ENOLCK;
+ }
+
/*
* Wakeup the list of locks to be retried.
*/
@@ -1520,6 +1585,7 @@ lf_clearlock (lockf_t *unlock, lockf_t **clean, HANDLE fhdl)
lf = overlap->lf_next;
overlap->lf_next = *clean;
*clean = overlap;
+ first_loop = false;
continue;
case 4: /* overlap starts before lock */
@@ -1527,6 +1593,7 @@ lf_clearlock (lockf_t *unlock, lockf_t **clean, HANDLE fhdl)
prev = &overlap->lf_next;
lf = overlap->lf_next;
overlap->create_lock_obj ();
+ first_loop = false;
continue;
case 5: /* overlap ends after lock */
diff --git a/winsup/cygwin/include/asm/socket.h b/winsup/cygwin/include/asm/socket.h
index 9aeb889..276df3a 100644
--- a/winsup/cygwin/include/asm/socket.h
+++ b/winsup/cygwin/include/asm/socket.h
@@ -17,8 +17,8 @@ details. */
#define IOC_IN 0x80000000 /* copy in parameters */
#define _IO(x,y) (IOC_VOID|(x<<8)|y)
-#define _IOR(x,y,t) (IOC_OUT|(((long)sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
-#define _IOW(x,y,t) (IOC_IN|(((long)sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
+#define _IOR(x,y,t) (IOC_OUT|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
+#define _IOW(x,y,t) (IOC_IN|((sizeof(t)&IOCPARM_MASK)<<16)|(x<<8)|y)
#define SIOCATMARK _IOR('s', 7, long) /* at oob mark? */
#define FIONREAD _IOR('f', 127, long) /* get # bytes to read */
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index 0f87fbc..fb821a6 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -11,7 +11,7 @@ details. */
changes to the DLL and is mainly informative in nature. */
#define CYGWIN_VERSION_DLL_MAJOR 3005
-#define CYGWIN_VERSION_DLL_MINOR 4
+#define CYGWIN_VERSION_DLL_MINOR 5
/* CYGWIN_VERSION_DLL_COMBINED gives us a single number representing the
combined DLL major and minor numbers. */
diff --git a/winsup/cygwin/include/getopt.h b/winsup/cygwin/include/getopt.h
index c5af1ac..63e068b 100644
--- a/winsup/cygwin/include/getopt.h
+++ b/winsup/cygwin/include/getopt.h
@@ -85,4 +85,4 @@ int getopt_long_only (int, char *const *, const char *, const struct option *, i
#endif /* __GETOPT_LONG_H__ */
#endif /* __UNISTD_GETOPT__ */
-#endif /*_INSIDE_NEWLIB*/
+#endif /*_LIBC */
diff --git a/winsup/cygwin/include/pthread.h b/winsup/cygwin/include/pthread.h
index 66d367d..8e29630 100644
--- a/winsup/cygwin/include/pthread.h
+++ b/winsup/cygwin/include/pthread.h
@@ -110,10 +110,13 @@ typedef struct _pthread_cleanup_handler
void _pthread_cleanup_push (__pthread_cleanup_handler *handler);
void _pthread_cleanup_pop (int execute);
-#define pthread_cleanup_push(_fn, _arg) { __pthread_cleanup_handler __cleanup_handler = \
- { _fn, _arg, NULL }; \
- _pthread_cleanup_push( &__cleanup_handler );
-#define pthread_cleanup_pop(_execute) _pthread_cleanup_pop( _execute ); }
+#define pthread_cleanup_push(_fn, _arg) \
+ do { \
+ __pthread_cleanup_handler __cleanup_handler = { _fn, _arg, NULL }; \
+ _pthread_cleanup_push(&__cleanup_handler)
+#define pthread_cleanup_pop(_execute) \
+ _pthread_cleanup_pop(_execute); \
+ } while (0)
/* Condition variables */
int pthread_cond_broadcast (pthread_cond_t *);
@@ -244,7 +247,7 @@ int pthread_getattr_np (pthread_t, pthread_attr_t *);
int pthread_getname_np (pthread_t, char *, size_t) __attribute__((__nonnull__(2)));
int pthread_setaffinity_np (pthread_t, size_t, const cpu_set_t *);
int pthread_setname_np (pthread_t, const char *) __attribute__((__nonnull__(2)));
-int pthread_sigqueue (pthread_t *, int, const union sigval);
+int pthread_sigqueue (pthread_t, int, const union sigval);
int pthread_timedjoin_np (pthread_t, void **, const struct timespec *);
int pthread_tryjoin_np (pthread_t, void **);
#endif
diff --git a/winsup/cygwin/local_includes/fhandler.h b/winsup/cygwin/local_includes/fhandler.h
index 87adca9..88a6b7d 100644
--- a/winsup/cygwin/local_includes/fhandler.h
+++ b/winsup/cygwin/local_includes/fhandler.h
@@ -1197,6 +1197,8 @@ class fhandler_pipe: public fhandler_pipe_fifo
private:
HANDLE read_mtx;
pid_t popen_pid;
+ bool was_blocking_read_pipe;
+ bool is_blocking_read_pipe;
HANDLE query_hdl;
HANDLE hdl_cnt_mtx;
HANDLE query_hdl_proc;
@@ -1287,6 +1289,7 @@ public:
}
static void spawn_worker (int fileno_stdin, int fileno_stdout,
int fileno_stderr);
+ static void sigproc_worker (void);
};
#define CYGWIN_FIFO_PIPE_NAME_LEN 47
@@ -1967,6 +1970,11 @@ class fhandler_termios: public fhandler_base
done_with_debugger /* The key was processed (CTRL_C_EVENT was sent)
for inferior of GDB. */
};
+ static bool process_alive (DWORD pid);
+ static DWORD get_console_process_id (DWORD pid, bool match,
+ bool cygwin = false,
+ bool stub_only = false,
+ bool nat = false);
public:
virtual pid_t tc_getpgid () { return 0; };
@@ -2019,6 +2027,7 @@ class fhandler_termios: public fhandler_base
virtual void setpgid_aux (pid_t pid) {}
virtual bool need_console_handler () { return false; }
virtual bool need_send_ctrl_c_event () { return true; }
+ static void atexit_func ();
struct ptys_handle_set_t
{
@@ -2089,7 +2098,7 @@ enum cltype
class dev_console
{
- pid_t owner;
+ DWORD owner;
bool is_legacy;
bool orig_virtual_terminal_processing_mode;
@@ -2160,6 +2169,8 @@ class dev_console
char *cons_rapoi;
bool cursor_key_app_mode;
bool disable_master_thread;
+ tty::cons_mode curr_input_mode;
+ tty::cons_mode curr_output_mode;
bool master_thread_suspended;
int num_processed; /* Number of input events in the current input buffer
already processed by cons_master_thread(). */
@@ -2180,10 +2191,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
{
@@ -2241,7 +2248,7 @@ private:
void set_cursor_maybe ();
static bool create_invisible_console_workaround (bool force);
static console_state *open_shared_console (HWND, HANDLE&, bool&);
- static void fix_tab_position (HANDLE h, pid_t owner);
+ static void fix_tab_position (HANDLE h, DWORD owner);
/* console mode calls */
const handle_set_t *get_handle_set (void) {return &handle_set;}
@@ -2366,9 +2373,9 @@ private:
static void set_console_mode_to_native ();
bool need_console_handler ();
static void set_disable_master_thread (bool x, fhandler_console *cons = NULL);
- static DWORD attach_console (pid_t, bool *err = NULL);
- static void detach_console (DWORD, pid_t);
- pid_t get_owner ();
+ static DWORD attach_console (DWORD, bool *err = NULL);
+ static void detach_console (DWORD, DWORD);
+ DWORD get_owner ();
void wpbuf_put (char c);
void wpbuf_send ();
int fstat (struct stat *buf);
@@ -2376,15 +2383,15 @@ 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);
};
+ void setup_pcon_hand_over ();
+ static void pcon_hand_over_proc ();
+
friend tty_min * tty_list::get_cttyp ();
};
@@ -2432,10 +2439,6 @@ class fhandler_pty_common: public fhandler_termios
}
void resize_pseudo_console (struct winsize *);
- static DWORD get_console_process_id (DWORD pid, bool match,
- bool cygwin = false,
- bool stub_only = false,
- bool nat = false);
bool to_be_read_from_nat_pipe (void);
static DWORD attach_console_temporarily (DWORD target_pid);
static void resume_from_temporarily_attach (DWORD resume_pid);
@@ -2870,11 +2873,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/mtinfo.h b/winsup/cygwin/local_includes/mtinfo.h
index 03aabbf..46f8b1b 100644
--- a/winsup/cygwin/local_includes/mtinfo.h
+++ b/winsup/cygwin/local_includes/mtinfo.h
@@ -101,7 +101,7 @@ class mtinfo_drive
int set_compression (HANDLE mt, int32_t count);
int set_blocksize (HANDLE mt, DWORD count);
int get_status (HANDLE mt, struct mtget *get);
- int set_options (HANDLE mt, int32_t options);
+ int set_options (HANDLE mt, uint32_t options);
int async_wait (HANDLE mt, DWORD *bytes_written);
public:
diff --git a/winsup/cygwin/local_includes/ntdll.h b/winsup/cygwin/local_includes/ntdll.h
index 7737ae5..4497fe5 100644
--- a/winsup/cygwin/local_includes/ntdll.h
+++ b/winsup/cygwin/local_includes/ntdll.h
@@ -23,7 +23,7 @@ extern GUID __cygwin_socket_guid;
/* Custom Cygwin-only status codes. */
#define STATUS_THREAD_SIGNALED ((NTSTATUS)0xe0000001)
#define STATUS_THREAD_CANCELED ((NTSTATUS)0xe0000002)
-#define STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION ((DWORD) 0xe0000269)
+#define STATUS_ILLEGAL_DLL_PSEUDO_RELOCATION ((NTSTATUS) 0xe0000269)
/* Simplify checking for a transactional error code. */
#define NT_TRANSACTIONAL_ERROR(s) \
diff --git a/winsup/cygwin/local_includes/select.h b/winsup/cygwin/local_includes/select.h
index 4e20212..dea0233 100644
--- a/winsup/cygwin/local_includes/select.h
+++ b/winsup/cygwin/local_includes/select.h
@@ -139,4 +139,9 @@ public:
extern "C" int cygwin_select (int , fd_set *, fd_set *, fd_set *,
struct timeval *to);
+ssize_t pipe_data_available (int, fhandler_base *, HANDLE, int);
+
+#define PDA_WRITE 0x01
+#define PDA_SELECT 0x02
+
#endif /* _SELECT_H_ */
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..2a047d7 100644
--- a/winsup/cygwin/local_includes/tty.h
+++ b/winsup/cygwin/local_includes/tty.h
@@ -178,6 +178,7 @@ public:
friend class fhandler_pty_master;
friend class fhandler_pty_slave;
friend class tty_min;
+ friend class fhandler_console;
};
class tty_list
@@ -211,4 +212,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/local_includes/winlean.h b/winsup/cygwin/local_includes/winlean.h
index 5bf1be2..62b651b 100644
--- a/winsup/cygwin/local_includes/winlean.h
+++ b/winsup/cygwin/local_includes/winlean.h
@@ -53,7 +53,10 @@ details. */
#define __undef_CRITICAL
#endif
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Warray-bounds"
#include <windows.h>
+#pragma GCC diagnostic pop
#include <wincrypt.h>
#include <lmcons.h>
#include <ntdef.h>
diff --git a/winsup/cygwin/net.cc b/winsup/cygwin/net.cc
index 08c584f..737e494 100644
--- a/winsup/cygwin/net.cc
+++ b/winsup/cygwin/net.cc
@@ -1912,7 +1912,7 @@ freeifaddrs (struct ifaddrs *ifp)
}
int
-get_ifconf (struct ifconf *ifc, int what)
+get_ifconf (struct ifconf *ifc, unsigned int what)
{
__try
{
diff --git a/winsup/cygwin/nlsfuncs.cc b/winsup/cygwin/nlsfuncs.cc
index b32fecc..f57465a 100644
--- a/winsup/cygwin/nlsfuncs.cc
+++ b/winsup/cygwin/nlsfuncs.cc
@@ -319,8 +319,7 @@ locale_cmp (const void *a, const void *b)
return strcmp (*la, *lb);
}
-/* Helper function to workaround reallocs which move blocks even if they shrink.
- Cygwin's realloc is not doing this, but tcsh's, for instance. All lc_foo
+/* Helper function to adjust pointers inside an lc_foo buffer. All lc_foo
structures consist entirely of pointers so they are practically pointer
arrays. What we do here is just treat the lc_foo pointers as char ** and
rebase all char * pointers within, up to the given size of the structure. */
@@ -334,6 +333,28 @@ rebase_locale_buf (const void *ptrv, const void *ptrvend, const char *newbase,
*ptrs += newbase - oldbase;
}
+/* Helper function to shrink an lc_foo buffer, adjusting pointers */
+static int
+shrink_locale_buf (const void *ptrv, const void *ptrvend,
+ char *oldbase, const char *oldend,
+ char **result)
+{
+ size_t minsize = oldend - oldbase;
+ char *tmp = (char *) malloc (minsize);
+ if (!tmp)
+ {
+ free (oldbase);
+ return -1;
+ }
+
+ memcpy (tmp, oldbase, minsize);
+ rebase_locale_buf (ptrv, ptrvend, tmp, oldbase, oldend);
+ free (oldbase);
+
+ *result = tmp;
+ return 1;
+}
+
static wchar_t *
__getlocaleinfo (wchar_t *loc, LCTYPE type, char **ptr, size_t size)
{
@@ -687,19 +708,20 @@ __set_lc_time_from_win (const char *name,
len += (wcslen (era->era_t_fmt) + 1) * sizeof (wchar_t);
len += (wcslen (era->alt_digits) + 1) * sizeof (wchar_t);
- /* Make sure data fits into the buffer */
+ /* If necessary, grow the buffer to ensure data fits into it */
if (lc_time_ptr + len > lc_time_end)
{
len = lc_time_ptr + len - new_lc_time_buf;
- char *tmp = (char *) realloc (new_lc_time_buf, len);
+ char *tmp = (char *) malloc (len);
if (!tmp)
era = NULL;
else
{
- if (tmp != new_lc_time_buf)
- rebase_locale_buf (_time_locale, _time_locale + 1, tmp,
- new_lc_time_buf, lc_time_ptr);
+ memcpy (tmp, new_lc_time_buf, MAX_TIME_BUFFER_SIZE);
+ rebase_locale_buf (_time_locale, _time_locale + 1, tmp,
+ new_lc_time_buf, lc_time_ptr);
lc_time_ptr = tmp + (lc_time_ptr - new_lc_time_buf);
+ free(new_lc_time_buf);
new_lc_time_buf = tmp;
lc_time_end = new_lc_time_buf + len;
}
@@ -752,17 +774,9 @@ __set_lc_time_from_win (const char *name,
}
}
- char *tmp = (char *) realloc (new_lc_time_buf, lc_time_ptr - new_lc_time_buf);
- if (!tmp)
- {
- free (new_lc_time_buf);
- return -1;
- }
- if (tmp != new_lc_time_buf)
- rebase_locale_buf (_time_locale, _time_locale + 1, tmp,
- new_lc_time_buf, lc_time_ptr);
- *lc_time_buf = tmp;
- return 1;
+ return shrink_locale_buf(_time_locale, _time_locale + 1,
+ new_lc_time_buf, lc_time_ptr,
+ lc_time_buf);
}
/* Called from newlib's setlocale() via __ctype_load_locale() if category
@@ -824,18 +838,9 @@ __set_lc_ctype_from_win (const char *name,
}
}
- char *tmp = (char *) realloc (new_lc_ctype_buf,
- lc_ctype_ptr - new_lc_ctype_buf);
- if (!tmp)
- {
- free (new_lc_ctype_buf);
- return -1;
- }
- if (tmp != new_lc_ctype_buf)
- rebase_locale_buf (_ctype_locale, _ctype_locale + 1, tmp,
- new_lc_ctype_buf, lc_ctype_ptr);
- *lc_ctype_buf = tmp;
- return 1;
+ return shrink_locale_buf(_ctype_locale, _ctype_locale + 1,
+ new_lc_ctype_buf, lc_ctype_ptr,
+ lc_ctype_buf);
}
/* Called from newlib's setlocale() via __numeric_load_locale() if category
@@ -900,18 +905,9 @@ __set_lc_numeric_from_win (const char *name,
_numeric_locale->codeset = lc_numeric_ptr;
lc_numeric_ptr = stpcpy (lc_numeric_ptr, charset) + 1;
- char *tmp = (char *) realloc (new_lc_numeric_buf,
- lc_numeric_ptr - new_lc_numeric_buf);
- if (!tmp)
- {
- free (new_lc_numeric_buf);
- return -1;
- }
- if (tmp != new_lc_numeric_buf)
- rebase_locale_buf (_numeric_locale, _numeric_locale + 1, tmp,
- new_lc_numeric_buf, lc_numeric_ptr);
- *lc_numeric_buf = tmp;
- return 1;
+ return shrink_locale_buf(_numeric_locale, _numeric_locale + 1,
+ new_lc_numeric_buf, lc_numeric_ptr,
+ lc_numeric_buf);
}
/* Called from newlib's setlocale() via __monetary_load_locale() if category
@@ -1039,18 +1035,9 @@ __set_lc_monetary_from_win (const char *name,
_monetary_locale->codeset = lc_monetary_ptr;
lc_monetary_ptr = stpcpy (lc_monetary_ptr, charset) + 1;
- char *tmp = (char *) realloc (new_lc_monetary_buf,
- lc_monetary_ptr - new_lc_monetary_buf);
- if (!tmp)
- {
- free (new_lc_monetary_buf);
- return -1;
- }
- if (tmp != new_lc_monetary_buf)
- rebase_locale_buf (_monetary_locale, _monetary_locale + 1, tmp,
- new_lc_monetary_buf, lc_monetary_ptr);
- *lc_monetary_buf = tmp;
- return 1;
+ return shrink_locale_buf(_monetary_locale, _monetary_locale + 1,
+ new_lc_monetary_buf, lc_monetary_ptr,
+ lc_monetary_buf);
}
extern "C" int
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index bfd338e..a5f5d6e 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -118,7 +118,7 @@ pinfo_init (char **envp, int envc)
DWORD
pinfo::status_exit (DWORD x)
{
- switch (x)
+ switch ((NTSTATUS) x)
{
case STATUS_DLL_NOT_FOUND:
{
diff --git a/winsup/cygwin/posix_timer.cc b/winsup/cygwin/posix_timer.cc
index 9d832f2..a336b2b 100644
--- a/winsup/cygwin/posix_timer.cc
+++ b/winsup/cygwin/posix_timer.cc
@@ -530,6 +530,7 @@ timer_delete (timer_t timerid)
__leave;
}
delete in_tt;
+ ret = 0;
}
__except (EFAULT) {}
__endtry
diff --git a/winsup/cygwin/release/3.5.4 b/winsup/cygwin/release/3.5.4
index 2a5f2b1..90c324b 100644
--- a/winsup/cygwin/release/3.5.4
+++ b/winsup/cygwin/release/3.5.4
@@ -15,3 +15,16 @@ 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
+
+- Fix an off-by-one in LC_MESSAGE wide character data.
+ Addresses: https://sourceware.org/pipermail/newlib/2024/021271.html
+
+- Improve write pipe behaviour in case the pipe buffer is about to be
+ filled up.
diff --git a/winsup/cygwin/release/3.5.5 b/winsup/cygwin/release/3.5.5
new file mode 100644
index 0000000..2ca4572
--- /dev/null
+++ b/winsup/cygwin/release/3.5.5
@@ -0,0 +1,35 @@
+Fixes:
+------
+
+- Fix undesired behaviour of console master thread in win32-input-mode
+ which is supported by Windows Termainal.
+ Addresses: https://cygwin.com/pipermail/cygwin/2024-August/256380.html
+
+- Fix a regression in 3.5.4 that writing to pipe extremely slows down.
+ Addresses: https://cygwin.com/pipermail/cygwin/2024-August/256398.html
+
+- Fix pread() and pwrite() EBADF error after fork().
+ Addresses: https://sourceware.org/pipermail/cygwin/2024-September/256468.html
+
+- Fix timer_delete() return value which always indicated failure.
+
+- Fix lockf() error which occurs when adding a new lock over multiple
+ locks.
+ Addresses: https://cygwin.com/pipermail/cygwin/2024-October/256528.html
+
+- Make lockf() return ENOLCK when the number of locks exceeds
+ MAX_LOCKF_CNT rather than printing a warning message.
+ Addresses: https://cygwin.com/pipermail/cygwin/2024-October/256528.html
+
+- Make console inherit hand over of pseudo console ownership from
+ parent pty.
+ Addresses: https://cygwin.com/pipermail/cygwin/2024-February/255388.html
+
+- Restore pipe blocking mode for non-cygwin apps.
+ Addresses: https://github.com/git-for-windows/git/issues/5115
+
+- Fix a problem that signal handler destroys the FPU context.
+ Addresses: https://cygwin.com/pipermail/cygwin/2024-October/256503.html
+
+- Fix type of pthread_sigqueue() first parameter to match Linux.
+ Addresses: https://cygwin.com/pipermail/cygwin/2024-September/256439.html
diff --git a/winsup/cygwin/scripts/gendef b/winsup/cygwin/scripts/gendef
index 3b1f8b9..c2ad5c7 100755
--- a/winsup/cygwin/scripts/gendef
+++ b/winsup/cygwin/scripts/gendef
@@ -213,10 +213,10 @@ sigdelayed:
.seh_pushreg %rbx
pushq %rax
.seh_pushreg %rax
- subq \$0x128,%rsp
- .seh_stackalloc 0x128
- stmxcsr 0x124(%rsp)
- fnstcw 0x120(%rsp)
+ subq \$0x148,%rsp
+ .seh_stackalloc 0x148
+ stmxcsr 0x13c(%rsp)
+ fnstenv 0x120(%rsp)
movdqa %xmm15,0x110(%rsp)
movdqa %xmm14,0x100(%rsp)
movdqa %xmm13,0xf0(%rsp)
@@ -275,10 +275,9 @@ sigdelayed:
movdqa 0xf0(%rsp),%xmm13
movdqa 0x100(%rsp),%xmm14
movdqa 0x110(%rsp),%xmm15
- fninit
- fldcw 0x120(%rsp)
- ldmxcsr 0x124(%rsp)
- addq \$0x128,%rsp
+ fldenv 0x120(%rsp)
+ ldmxcsr 0x13c(%rsp)
+ addq \$0x148,%rsp
popq %rax
popq %rbx
popq %rcx
diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc
index 725aab9..bc02c3f 100644
--- a/winsup/cygwin/select.cc
+++ b/winsup/cygwin/select.cc
@@ -584,14 +584,15 @@ no_verify (select_record *, fd_set *, fd_set *, fd_set *)
return 0;
}
-static int
-pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
+ssize_t
+pipe_data_available (int fd, fhandler_base *fh, HANDLE h, int flags)
{
if (fh->get_device () == FH_PIPER)
{
DWORD nbytes_in_pipe;
- if (!writing && PeekNamedPipe (h, NULL, 0, NULL, &nbytes_in_pipe, NULL))
- return nbytes_in_pipe > 0;
+ if (!(flags & PDA_WRITE)
+ && PeekNamedPipe (h, NULL, 0, NULL, &nbytes_in_pipe, NULL))
+ return nbytes_in_pipe;
return -1;
}
@@ -609,9 +610,17 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
access on the write end. */
select_printf ("fd %d, %s, NtQueryInformationFile failed, status %y",
fd, fh->get_name (), status);
- return writing ? 1 : -1;
+ switch (flags)
+ {
+ case PDA_WRITE:
+ return 1;
+ case PDA_SELECT | PDA_WRITE:
+ return PIPE_BUF;
+ default:
+ return -1;
+ }
}
- if (writing)
+ if (flags & PDA_WRITE)
{
/* If there is anything available in the pipe buffer then signal
that. This means that a pipe could still block since you could
@@ -638,20 +647,26 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
/* Note: Do not use NtQueryInformationFile() for query_hdl because
NtQueryInformationFile() seems to interfere with reading pipes
in non-cygwin apps. Instead, use PeekNamedPipe() here. */
+ /* Note 2: we return the number of available bytes. Select for writing
+ returns writable *only* if at least PIPE_BUF bytes are left in the
+ buffer. If we can't fetch the real number of available bytes, the
+ number of bytes returned depends on the caller. For select we return
+ PIPE_BUF to fake writability, for writing we return 1 to allow
+ handling this fact. */
if (fh->get_device () == FH_PIPEW && fpli.WriteQuotaAvailable == 0)
{
HANDLE query_hdl = ((fhandler_pipe *) fh)->get_query_handle ();
if (!query_hdl)
query_hdl = ((fhandler_pipe *) fh)->temporary_query_hdl ();
- if (!query_hdl)
- return 1; /* We cannot know actual write pipe space. */
+ if (!query_hdl) /* We cannot know actual write pipe space. */
+ return (flags & PDA_SELECT) ? PIPE_BUF : 1;
DWORD nbytes_in_pipe;
BOOL res =
PeekNamedPipe (query_hdl, NULL, 0, NULL, &nbytes_in_pipe, NULL);
if (!((fhandler_pipe *) fh)->get_query_handle ())
CloseHandle (query_hdl); /* Close temporary query_hdl */
- if (!res)
- return 1;
+ if (!res) /* We cannot know actual write pipe space. */
+ return (flags & PDA_SELECT) ? PIPE_BUF : 1;
fpli.WriteQuotaAvailable = fpli.InboundQuota - nbytes_in_pipe;
}
if (fpli.WriteQuotaAvailable > 0)
@@ -659,7 +674,7 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
paranoid_printf ("fd %d, %s, write: size %u, avail %u", fd,
fh->get_name (), fpli.InboundQuota,
fpli.WriteQuotaAvailable);
- return 1;
+ return fpli.WriteQuotaAvailable;
}
/* TODO: Buffer really full or non-Cygwin reader? */
}
@@ -667,7 +682,7 @@ pipe_data_available (int fd, fhandler_base *fh, HANDLE h, bool writing)
{
paranoid_printf ("fd %d, %s, read avail %u", fd, fh->get_name (),
fpli.ReadDataAvailable);
- return 1;
+ return fpli.ReadDataAvailable;
}
if (fpli.NamedPipeState & FILE_PIPE_CLOSING_STATE)
return -1;
@@ -715,10 +730,10 @@ peek_pipe (select_record *s, bool from_select)
gotone = s->read_ready = true;
goto out;
}
- int n = pipe_data_available (s->fd, fh, h, false);
+ ssize_t n = pipe_data_available (s->fd, fh, h, PDA_SELECT);
/* On PTY masters, check if input from the echo pipe is available. */
if (n == 0 && fh->get_echo_handle ())
- n = pipe_data_available (s->fd, fh, fh->get_echo_handle (), false);
+ n = pipe_data_available (s->fd, fh, fh->get_echo_handle (), PDA_SELECT);
if (n < 0)
{
@@ -759,9 +774,9 @@ out:
gotone += s->except_ready = true;
return gotone;
}
- int n = pipe_data_available (s->fd, fh, h, true);
+ ssize_t n = pipe_data_available (s->fd, fh, h, PDA_SELECT | PDA_WRITE);
select_printf ("write: %s, n %d", fh->get_name (), n);
- gotone += s->write_ready = n;
+ gotone += s->write_ready = (n >= PIPE_BUF);
if (n < 0 && s->except_selected)
gotone += s->except_ready = true;
}
@@ -972,9 +987,10 @@ peek_fifo (select_record *s, bool from_select)
out:
if (s->write_selected)
{
- int n = pipe_data_available (s->fd, fh, fh->get_handle (), true);
+ ssize_t n = pipe_data_available (s->fd, fh, fh->get_handle (),
+ PDA_SELECT | PDA_WRITE);
select_printf ("write: %s, n %d", fh->get_name (), n);
- gotone += s->write_ready = n;
+ gotone += s->write_ready = (n >= PIPE_BUF);
if (n < 0 && s->except_selected)
gotone += s->except_ready = true;
}
@@ -1398,9 +1414,9 @@ out:
HANDLE h = ptys->get_output_handle ();
if (s->write_selected)
{
- int n = pipe_data_available (s->fd, fh, h, true);
+ ssize_t n = pipe_data_available (s->fd, fh, h, PDA_SELECT | PDA_WRITE);
select_printf ("write: %s, n %d", fh->get_name (), n);
- gotone += s->write_ready = n;
+ gotone += s->write_ready = (n >= PIPE_BUF);
if (n < 0 && s->except_selected)
gotone += s->except_ready = true;
}
diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc
index 86e4e60..a758bc8 100644
--- a/winsup/cygwin/sigproc.cc
+++ b/winsup/cygwin/sigproc.cc
@@ -1082,7 +1082,7 @@ child_info::proc_retry (HANDLE h)
if (!exit_code)
return EXITCODE_OK;
sigproc_printf ("exit_code %y", exit_code);
- switch (exit_code)
+ switch ((NTSTATUS) exit_code)
{
case STILL_ACTIVE: /* shouldn't happen */
sigproc_printf ("STILL_ACTIVE? How'd we get here?");
@@ -1475,14 +1475,7 @@ wait_sig (VOID *)
}
break;
case __SIGNONCYGCHLD:
- cygheap_fdenum cfd (false);
- while (cfd.next () >= 0)
- if (cfd->get_dev () == FH_PIPEW)
- {
- fhandler_pipe *pipe = (fhandler_pipe *)(fhandler_base *) cfd;
- if (pipe->need_close_query_hdl ())
- pipe->close_query_handle ();
- }
+ fhandler_pipe::sigproc_worker ();
break;
}
if (clearwait && !have_execed)
diff --git a/winsup/cygwin/spawn.cc b/winsup/cygwin/spawn.cc
index d01f678..f5a4b91 100644
--- a/winsup/cygwin/spawn.cc
+++ b/winsup/cygwin/spawn.cc
@@ -888,6 +888,7 @@ child_info_spawn::worker (const char *prog_arg, const char *const *argv,
ctrl_c_handler(). This insures that setting sigExeced
on Ctrl-C key has been completed. */
init_console_handler (false);
+ fhandler_termios::atexit_func ();
myself.exit (EXITCODE_NOSET);
break;
case _P_WAIT:
diff --git a/winsup/cygwin/thread.cc b/winsup/cygwin/thread.cc
index 0c6f570..9ee9650 100644
--- a/winsup/cygwin/thread.cc
+++ b/winsup/cygwin/thread.cc
@@ -3301,13 +3301,13 @@ pthread_sigmask (int operation, const sigset_t *set, sigset_t *old_set)
}
int
-pthread_sigqueue (pthread_t *thread, int sig, const union sigval value)
+pthread_sigqueue (pthread_t thread, int sig, const union sigval value)
{
siginfo_t si = {0};
- if (!pthread::is_good_object (thread))
+ if (!pthread::is_good_object (&thread))
return EINVAL;
- if (!(*thread)->valid)
+ if (!thread->valid)
return ESRCH;
si.si_signo = sig;
@@ -3315,7 +3315,7 @@ pthread_sigqueue (pthread_t *thread, int sig, const union sigval value)
si.si_value = value;
si.si_pid = myself->pid;
si.si_uid = myself->uid;
- return (int) sig_send (NULL, si, (*thread)->cygtls);
+ return (int) sig_send (NULL, si, thread->cygtls);
}
/* Cancelability */
diff --git a/winsup/cygwin/tty.cc b/winsup/cygwin/tty.cc
index bf7c601..2cd4ae6 100644
--- a/winsup/cygwin/tty.cc
+++ b/winsup/cygwin/tty.cc
@@ -323,7 +323,7 @@ tty::wait_fwd ()
thread when the last data is transfered. */
const ULONGLONG sleep_in_nat_pipe = 16;
const ULONGLONG time_to_wait = sleep_in_nat_pipe * 2 + 1/* margine */;
- ULONGLONG elapsed;
+ ULONGLONG elapsed = 0;
while (fwd_not_empty
|| (elapsed = GetTickCount64 () - fwd_last_time) < time_to_wait)
{
diff --git a/winsup/utils/kill.cc b/winsup/utils/kill.cc
index fb45e4c..bcabcd4 100644
--- a/winsup/utils/kill.cc
+++ b/winsup/utils/kill.cc
@@ -73,7 +73,7 @@ print_version ()
static const char *
strsigno (int signo)
{
- static char sigbuf[8];
+ static char sigbuf[32];
if (signo > 0 && signo < SIGRTMIN)
return sys_sigabbrev[signo];