Put more thought into new signaling code

This commit is contained in:
Justine Tunney 2024-09-19 20:13:55 -07:00
parent 6107eb38f9
commit f68fc1f815
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
10 changed files with 127 additions and 51 deletions

View file

@ -465,7 +465,6 @@ textwindows int sys_fork_nt(uint32_t dwCreationFlags) {
__morph_tls();
__tls_enabled = true;
// the child's pending signals is initially empty
atomic_store_explicit(__sig.process, 0, memory_order_relaxed);
atomic_store_explicit(&tib->tib_sigpending, 0, memory_order_relaxed);
// re-apply code morphing for function tracing
if (ftrace_stackdigs)

View file

@ -59,11 +59,22 @@ textwindows int sys_kill_nt(int pid, int sig) {
if (pid <= 0 || pid == getpid()) {
if (sig) {
if (pid <= 0) {
// if pid is 0 or -1 then kill the processes beneath us too.
// this isn't entirely right but it's closer to being right.
// having this behavior is helpful for servers like redbean.
struct Dll *e;
BLOCK_SIGNALS;
__proc_lock();
for (e = dll_first(__proc.list); e; e = dll_next(__proc.list, e))
TerminateProcess(PROC_CONTAINER(e)->handle, sig);
for (e = dll_first(__proc.list); e; e = dll_next(__proc.list, e)) {
atomic_ulong *sigproc;
struct Proc *pr = PROC_CONTAINER(e);
if (sig != 9 && (sigproc = __sig_map_process(pid, kNtOpenExisting))) {
atomic_fetch_or_explicit(sigproc, 1ull << (sig - 1),
memory_order_release);
} else {
TerminateProcess(pr->handle, sig);
}
}
__proc_unlock();
ALLOW_SIGNALS;
}
@ -73,7 +84,25 @@ textwindows int sys_kill_nt(int pid, int sig) {
}
}
// attempt to signal via /var/sig shared memory file
// find existing handle we own for process
//
// this step should come first to verify process existence. this is
// because there's no guarantee that just because the shared memory
// file exists, the process actually exists.
int64_t handle, closeme = 0;
if (!(handle = __proc_handle(pid))) {
if ((handle = OpenProcess(kNtProcessTerminate, false, pid))) {
closeme = handle;
} else {
goto OnError;
}
}
// attempt to signal via shared memory file
//
// now that we know the process exists, if it has a shared memory file
// then we can be reasonably certain it's a cosmo process which should
// be trusted to deliver its signal, unless it's a nine exterminations
if (pid > 0 && sig != 9) {
atomic_ulong *sigproc;
if ((sigproc = __sig_map_process(pid, kNtOpenExisting))) {
@ -81,20 +110,12 @@ textwindows int sys_kill_nt(int pid, int sig) {
atomic_fetch_or_explicit(sigproc, 1ull << (sig - 1),
memory_order_release);
UnmapViewOfFile(sigproc);
if (closeme)
CloseHandle(closeme);
return 0;
}
}
// find existing handle we own for process
int64_t handle, closeme = 0;
if (!(handle = __proc_handle(pid))) {
if ((handle = OpenProcess(kNtProcessTerminate, false, pid))) {
closeme = handle;
} else {
goto OnError;
}
}
// perform actual kill
// process will report WIFSIGNALED with WTERMSIG(sig)
bool32 ok = TerminateProcess(handle, sig);

View file

@ -29,6 +29,17 @@
* The impact of this action can be terminating the process, or
* interrupting it to request something happen.
*
* On Windows, signals are delivered between processes using shared
* memory files stored in C:\ProgramData\cosmo\sig\x\y.pid which hold
* the process signal mask. Any process that can access these files can
* signal a cosmo process. The targeting process will then notice that a
* signal has been added and delivers to any thread as soon as possible.
*
* On Windows, the concept of a process group isn't fully implemented.
* Saying `kill(0, sig)` will deliver `sig` to all direct descendent
* processes. Saying `kill(-pid, sig)` will be the same as saying
* `kill(pid, sig)`.
*
* @param pid can be:
* >0 signals one process by id
* =0 signals all processes in current process group

View file

@ -323,6 +323,7 @@ textwindows int64_t __proc_search(int pid) {
int64_t handle = 0;
BLOCK_SIGNALS;
__proc_lock();
// TODO(jart): we should increment a reference count when returning
for (e = dll_first(__proc.list); e; e = dll_next(__proc.list, e)) {
if (pid == PROC_CONTAINER(e)->pid) {
handle = PROC_CONTAINER(e)->handle;