Previously, the retry flag was always set when pending_signal::pending()
was called. However, if the queue is empty sig thread tries to flush
the queue even though it is not necessary. With this patch, the retry
flag is set only if the queue is not empty.
Addresses: https://cygwin.com/pipermail/cygwin/2024-November/256744.html
Fixes: 5e31c80e4e ("(pending_signals::pending): Force an additional loop through wait_sig by setting retry whenever this function is called.")
Reported-by: Christian Franke <Christian.Franke@t-online.de>
Reviewed-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
With the previous code, the queued signal is tried to resend only when
a new signal arrives or pending_signals::pending() is called.
With this patch, if the signal is queued and the retry flag is not set
and the new signal is not received yet, the sig thread tries to handle
the queued signal again. Without this patch, the chance to handle the
queue would be delayed.
Addresses: https://cygwin.com/pipermail/cygwin/2024-November/256744.html
Fixes: 5e31c80e4e ("(pending_signals::pending): Force an additional loop through wait_sig by setting retry whenever this function is called.")
Reported-by: Christian Franke <Christian.Franke@t-online.de>
Reviewed-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Previously, a deadlock happened if many SIGSTOP/SIGCONT signals were
received rapidly. If the main thread sends __SIGFLUSH at the timing
when SIGSTOP is handled by the sig thread, but not is handled by the
main thread yet (sig_handle_tty_stop() not called yet), and if SIGCONT
is received, the sig thread waits for cygtls::current_sig (is SIGSTOP
now) cleared. However, the main thread waits for the pack.wakeup using
WaitForSingleObject(), so the main thread cannot handle SIGSTOP. This
is the mechanism of the deadlock. This patch uses cygwait() instead of
WaitForSingleObject() to be able to handle the pending SIGSTOP.
Addresses: https://cygwin.com/pipermail/cygwin/2024-November/256744.html
Fixes: 7759daa979 ("(sig_send): Fill out sigpacket structure to send to signal thread rather than racily sending separate packets.")
Reported-by: Christian Franke <Christian.Franke@t-online.de>
Reviewed-by: Corinna Vinschen <corinna@vinschen.de>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
It appears this is causing hangs on native x86_64 in similar scenarios
as the hangs on ARM64, because `CancelSynchronousIo` is returning `TRUE`
but not canceling the `ReadFile` call as expected.
Addresses: https://github.com/msys2/MSYS2-packages/issues/4340#issuecomment-2491401847
Fixes: b091b47b9e ("cygthread: suspend thread before terminating.")
Signed-off-by: Jeremy Drake <cygwin@jdrake.com>
This addresses an extremely difficult to debug deadlock when running
under emulation on ARM64.
A relatively easy way to trigger this bug is to call `fork()`, then within the
child process immediately call another `fork()` and then `exit()` the
intermediate process.
It would seem that there is a "code emulation" lock on the wait thread at
this stage, and if the thread is terminated too early, that lock still exists
albeit without a thread, and nothing moves forward.
It seems that a `SuspendThread()` combined with a `GetThreadContext()`
(to force the thread to _actually_ be suspended, for more details see
https://devblogs.microsoft.com/oldnewthing/20150205-00/?p=44743)
makes sure the thread is "booted" from emulation before it is suspended.
Hopefully this means it won't be holding any locks or otherwise leave
emulation in a bad state when the thread is terminated.
Also, attempt to use `CancelSynchonousIo()` (as seen in `flock.cc`) to avoid
the need for `TerminateThread()` altogether. This doesn't always work,
however, so was not a complete fix for the deadlock issue.
Addresses: https://cygwin.com/pipermail/cygwin-developers/2024-May/012694.html
Signed-off-by: Jeremy Drake <cygwin@jdrake.com>
Previously, cygwin read pipe used non-blocking mode although non-
cygwin app uses blocking-mode by default. Despite this requirement,
if a cygwin app is executed from a non-cygwin app and the cygwin
app exits, read pipe remains on non-blocking mode because of the
commit fc691d0246. Due to this behaviour, the non-cygwin app
cannot read the pipe correctly after that. Similarly, if a non-
cygwin app is executed from a cygwin app and the non-cygwin app
exits, the read pipe mode remains on blocking mode although cygwin
read pipe should be non-blocking mode.
These bugs were provoked by pipe mode toggling between cygwin and
non-cygwin apps. To make management of pipe mode simpler, this
patch has re-designed the pipe implementation. In this new
implementation, both read and write pipe basically use only blocking
mode and the behaviour corresponding to the pipe mode is simulated
in raw_read() and raw_write(). Only when NtQueryInformationFile
(FilePipeLocalInformation) fails for some reasons, the raw_read()/
raw_write() cannot simulate non-blocking access. Therefore, the pipe
mode is temporarily changed to non-blocking mode.
Moreover, because the fact that NtSetInformationFile() in
set_pipe_non_blocking(true) fails with STATUS_PIPE_BUSY if the pipe
is not empty has been found, query handle is not necessary anymore.
This allows the implementation much simpler than before.
Addresses: https://github.com/git-for-windows/git/issues/5115
Fixes: fc691d0246 ("Cygwin: pipe: Make sure to set read pipe non-blocking for cygwin apps.");
Reported-by: isaacag, Johannes Schindelin <Johannes.Schindelin@gmx.de>
Reviewed-by: Corinna Vinschen <corinna@vinschen.de>, Ken Brown <kbrown@cornell.edu>
Signed-off-by: Takashi Yano <takashi.yano@nifty.ne.jp>
Fix warnings with gcc 12 about narrowing conversions of NTSTATUS
constants when used as case labels, e.g:
> ../../../../src/winsup/cygwin/exceptions.cc: In static member function ‘static int exception::handle(EXCEPTION_RECORD*, void*, CONTEXT*, PDISPATCHER_CONTEXT)’:
> ../../../../src/winsup/cygwin/exceptions.cc:670:10: error: narrowing conversion of ‘-1073741682’ from ‘NTSTATUS’ {aka ‘int’} to ‘unsigned int’ [-Wnarrowing]
See also: c5bdf60ac4
Signed-off-by: Jon Turney <jon.turney@dronecode.org.uk>
The code computing the mask of pending signals used the per-queued
signal TLS pointer without checking it for NULL. Fix this by using
the process-wide signal mask in that case.
Fixes: 195169186b ("Cygwin: wait_sig: allow to compute process-wide mask of pending signals")
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Even after fork, we might need the parent sigmask without having
access to the real _main_tls. There's a short time at process startup,
when _main_tls points to the system-allocated stack, but wait_sig is
already running. If we can't lock _main_tls, because find_tls can't
find it yet, we now access the parent's sigmask via child_info.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
- As mentioned in commit message of the commit b531d6b0, if multiple
writers including non-cygwin app exist, the non-cygwin app cannot
detect pipe closure on the read side when the pipe is created by
system account or the the pipe creator is running as service.
This is because query_hdl which is held in write side also is a
read end of the pipe, so the pipe is still alive for the non-cygwin
app even after the reader is closed.
To avoid this problem, this patch lets all processes in the same
process group close query_hdl using newly introduced internal signal
__SIGNONCYGCHLD when non-cygwin app is started.
Addresses: https://cygwin.com/pipermail/cygwin/2022-March/251097.html
So far the values of SigPnd and SigBlk were always 0 and SigIgn
was incorrectly set to the block mask of the current thread of
the calling process.
Fix that by adding a _pinfo::siginfo method and a PICOM_SIGINFO
message to allow to request actual signal info of any running process.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
- When Ctrl-C terminates a non-cygwin process on a pseudo console,
pty master attaches to the pseudo console first, and send
CTRL_C_EVENT. If the non-cygwin process closes the pseudo console
before the pty master calls FreeConsole(), the pty master process
will crash. With this patch, pty master process takes over the
ownership of the pseudo console, and closes it by myself.
- The recent change by the commit "Cygwin: console: Redesign handling
of special keys." breaks the handling of CTRL_BREAK_EVENT. The login
shell in console exits on Ctrl-Break key. This patch fixes the issue.
- This patch rearranges the cooperation between cons_master_thread,
line_edit, and ctrl_c_handler so that only one of them operates
at the same time. Since these handle Ctrl-C individually, so the
signal may be sent multiple times to the process. This patch fixes
the issue.
- This patch fixes the issue that process sometimes hangs for 60
seconds with the following scenario.
1) Open command prompt.
2) Run "c:\cygwin64\bin\bash -l"
3) Compipe the following source with mingw compiler.
/*--- Begin ---*/
#include <stdio.h>
int main() {return getchar();}
/*---- End ----*/
4) Run "tcsh -c ./a.exe"
5) Hit Ctrl-C.
- Currently, bash occasionally exits by Ctrl-C with the following
scenario.
1) Start bash in the command prompt.
2) Run 'exec bash'.
3) Press Ctrl-C several times.
This patch fixes the issue.
We need one more entry than max children in the arrays.
There's no reason to do this for the static array, though.
One more entry in the overflow array is sufficient.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
On PROC_EXEC_CLEANUP, the pinfo's in chld_procs are removed.
This is done in a loop always removing the child with index 0.
This, however, results in copying the last child's pinfo in
chld_procs to position 0. Do this for 100 children and you
get 99 entirely useless copy operations.
Fix this by calling remove_proc in reverse order.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
256 children per process is a bit tight in some scenarios.
Fix this by revamping the `procs' array. Convert it to an
extensible class child_procs and rename procs to chld_procs.
Fix code throughout to use matching class methods rather than
direct access.
To allow a lot more child processes while trying to avoid
allocations at DLL startup, maintain two arrays within class
child_procs, one using a default size for 255 (i686) or 1023
(x86_64) children, the other, dynamically allocated on overflowing
the first array, giving room for another 1023 (i686) or 4095
(x86_64) processes.
On testing with a simple reproducer on a x86_64 machine with
4 Gigs RAM, a system memory overflow occured after forking
about 1450 child processes, so this simple dynamic should
suffice for a while.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
pinfo::remember with the detach parameter set to true is
the only way to call proc_subproc with PROC_DETACHED_CHILD.
This call is exclusively used in spawn to set up a pinfo for
a detached child, and that pinfo goes out of scope right
afterwards without any further action.
Drop the flag and drop the detach parameter from pinfo::remember.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
The return value is used in a numerical context and remove_proc
already returned inconsistently "true" vs. 0.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
After patch 23a779bf3d
"Cygwin: pinfo: stop remember doing reattach",
PROC_ADDCHILD actually just sets up a new child, mirroring
PROC_DETACHED_CHILD. The actual attaching of the child is
performed by action PROC_REATTACH_CHILD or pinfo::reattach
respectively.
To better reflect what's going on, rename PROC_REATTACH_CHILD
to PROC_ATTACH_CHILD and rename pinfo::reattach to pinfo::attach.
For better readability change PROC_ADDCHILD to PROC_ADD_CHILD.
Fix comments accordingly.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This patch has been inspired by the Linux kernel patch
294f69e662d1 compiler_attributes.h: Add 'fallthrough' pseudo keyword for switch/case use
written by Joe Perches <joe AT perches DOT com> based on an idea from
Dan Carpenter <dan DOT carpenter AT oracle DOT com>. The following text
is from the original log message:
Reserve the pseudo keyword 'fallthrough' for the ability to convert the
various case block /* fallthrough */ style comments to appear to be an
actual reserved word with the same gcc case block missing fallthrough
warning capability.
All switch/case blocks now should end in one of:
break;
fallthrough;
goto <label>;
return [expression];
continue;
In C mode, GCC supports the __fallthrough__ attribute since 7.1,
the same time the warning and the comment parsing were introduced.
Cygwin-only: add an explicit -Wimplicit-fallthrough=5 to the build
flags.
NSIG is a deprecated symbol only visible under MISC visibility.
_NSIG is used widely instead, and on most systems NSIG is
defined in terms of _NSIG.
Follow suit: Change NSIG to _NSIG throughout and change visiblity
of NSIG to be defined only in __MISC_VISIBLE case.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Commit 5a0f2c00aa "Cygwin: fork/exec: fix child process permissions"
removed the PROCESS_DUP_HANDLE handle permission of the parent process
handle in the child to avoid a security problem.
It turned out that this broke the following scenario: If a process forks
and then the parent execs, the child loses the ability to register the
parent's death. To wit, after the parent died the child process does
not set its own PPID to 1 anymore.
The current exec mechanism copies required handle values (handles to
keep contact to the child processes) into the child_info for the
about-to-be-exec'ed process. The exec'ed process is supposed to
duplicate these handles. This fails, given that we don't allow the
exec'ed process PROCESS_DUP_HANDLE access to the exec'ing process since
commit 5a0f2c00aa.
The fix is to avoid the DuplicateHandle calls in the exec'ed process.
This patch sets the affected handles to "inheritable" in the exec'ing
process at exec time. The exec'ed process just copies the handle values
and resets handle inheritance to "non-inheritable". The exec'ing
process doesn't have to reset handle inheritance, it exits after setting
up the exec'ed process anyway.
Testcase: $ ssh-agent /bin/sleep 3
ssh-agent forks and the parent exec's sleep. After sleep exits, `ps'
should show ssh-agent to have PPID 1, and eventually ssh-agent exits.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Rather than waiting for signalfd_select_wait in a thread, which is racy,
create a global event "my_pendingsigs_evt" which is set and reset by
wait_sig depending only on the fact if blocked signals are pending or not.
This in turn allows to WFMO on this event in select as soon as signalfds
are present in the read descriptor set. Select's peek and verify
will then check if one of the present signalfds is affected.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
During fork, the child process requires the process table to be
initialized for fixup_shms_after_fork, while still allowing subsequent
dlls.load_after_fork to fail silently (for when the "forkable" hardlinks
are not created yet).
pinfo::remember not performing reattach anymore requires explicit
pinfo::reattach now where appropriate.
Prepares to improve "Cygwin: fork: Remember child not before success."
commit f03ea8e1c5, which leads to fork
problems if cygserver is running:
https://cygwin.com/ml/cygwin-patches/2019-q2/msg00155.html
The sigpending mechanism failed to check if the pending signal was a
process-wide signal, or a signal for the curent thread. Fix that by
adding a matching conditional to wait_sig's __SIGPENDING code.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
So far sig_send's return type is int. The problem with this is
that sig_send returns a sigset_t on __SIGPENDING, and sigset_t
is defined as long type. So the function only returns the lower
32 bit of sigset_t, which is fine on 32 bit, but casts away the
pending RT signals on 64 bit.
Fix this by changing the return type of sig_send to sigset_t, so
as not to narrow down the sigset when returning from handling
__SIGPENDING. Make sure to cast correctly in all invocations
of sig_send.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
To support in-cygwin package managers, the fork() implementation must
not rely on .exe and .dll files to stay in their original location, as
the package manager's job is to replace these files. Instead, when the
first fork try fails, and we have NTFS, we use hardlinks to the original
binaries in /var/run/cygfork/ to create the child process during the
second fork try, along the main.exe.local file to enable the "DotLocal
Dll Redirection" feature for the dlls.
The (probably few) users that need an update-safe fork manually have to
create the /var/run/cygfork/ directory for now, using:
mkdir --mode=a=rwxt /var/run/cygfork
* child_info.h: Bump CURR_CHILD_INFO_MAGIC.
(enum child_status): Add _CI_SILENTFAIL flag.
(struct child_info): Add silentfail setter and getter.
* winsup.h (child_copy): Add bool silentfail parameter.
* cygheap.cc: Pass silentfail parameter to child_copy.
* dcrt0.cc: Ditto.
* dll_init.h (struct dll): Define public inline method forkedntname.
(struct dll_list): Declare private method find_by_forkedntname.
* dll_init.cc (struct dll_list): Implement find_by_forkedntname.
(dll_list::alloc): Use find_by_forkedntname when in load after fork.
(dll_list::load_after_fork_impl): Load dlls using dll::forkedntname.
* fork.cc (frok::parent): Set silentfail child info flag. Pass
silentfail parameter to child_copy. Use forkedntname of
dlls.main_executable.
(fork): When first dofork run failed and did not use forkables,
run dofork again with_forkables set to true.
(child_copy): Use debug_printf if silentfail is true,
system_printf otherwise.
VirtualQueryEx, called by fixup_mmaps_after_fork, requires
PROCESS_QUERY_INFORMATION permissions per MSDN. However, testing
shows that PROCESS_QUERY_LIMITED_INFORMATION is sufficient when
running the same code on Windows 8.1 or Windows 10. Fix the code
to give the forked child always PROCESS_QUERY_INFORMATION perms
on Windows Vista/7 and respective server releases.
Revert now unneeded patch to check_token_membership as well.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Keeping an inheritable handle open results in that handle being
spilled over into grandchild processes, which is not desired.
Duplicate original parent handle into a non-inheritable one with
minimal SYNCHRONIZE permissions and close the original handle.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
- Exec'ed/spawned processes don't need PROCESS_DUP_HANDLE. Remove that
permission from the parent handle.
- PROCESS_QUERY_LIMITED_INFORMATION doesn't work for Windows 7 if the
process is started as a service. Add PROCESS_QUERY_INFORMATION for
pre-Windows 8 in that case.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>