mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-02 17:28:30 +00:00
Introduce interprocess signaling on Windows
This change gets rsync working without any warning or errors. On Windows we now create a bunch of C:\var\sig\x\y.pid shared memory files, so sigs can be delivered between processes. WinMain() creates this file when the process starts. If the program links signaling system calls then we make a thread at startup too, which allows asynchronous delivery each quantum and cancelation points can spot these signals potentially faster on wait See #1240
This commit is contained in:
parent
8527462b95
commit
0d74673213
22 changed files with 302 additions and 62 deletions
|
@ -196,9 +196,13 @@ textwindows void WinMainForked(void) {
|
|||
int64_t reader;
|
||||
int64_t savetsc;
|
||||
uint32_t varlen;
|
||||
atomic_ulong *sigproc;
|
||||
char16_t fvar[21 + 1 + 21 + 1];
|
||||
struct Fds *fds = __veil("r", &g_fds);
|
||||
|
||||
// save signal pointer
|
||||
sigproc = __sig.process;
|
||||
|
||||
// check to see if the process was actually forked
|
||||
// this variable should have the pipe handle numba
|
||||
varlen = GetEnvironmentVariable(u"_FORK", fvar, ARRAYLEN(fvar));
|
||||
|
@ -295,12 +299,13 @@ textwindows void WinMainForked(void) {
|
|||
fds->p[1].handle = GetStdHandle(kNtStdOutputHandle);
|
||||
fds->p[2].handle = GetStdHandle(kNtStdErrorHandle);
|
||||
|
||||
// restore signal pointer
|
||||
__sig.process = sigproc;
|
||||
|
||||
// restore the crash reporting stuff
|
||||
#if SYSDEBUG
|
||||
RemoveVectoredExceptionHandler(oncrash);
|
||||
#endif
|
||||
if (_weaken(__sig_init))
|
||||
_weaken(__sig_init)();
|
||||
|
||||
// jump back into function below
|
||||
longjmp(jb, 1);
|
||||
|
@ -460,15 +465,16 @@ 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.pending, 0, memory_order_relaxed);
|
||||
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) {
|
||||
if (ftrace_stackdigs)
|
||||
_weaken(__hook)(_weaken(ftrace_hook), _weaken(GetSymbolTable)());
|
||||
}
|
||||
// reset core runtime services
|
||||
__proc_wipe();
|
||||
WipeKeystrokes();
|
||||
if (_weaken(__sig_init))
|
||||
_weaken(__sig_init)();
|
||||
if (_weaken(__itimer_wipe))
|
||||
_weaken(__itimer_wipe)();
|
||||
// notify pthread join
|
||||
|
|
|
@ -16,16 +16,21 @@
|
|||
│ TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR │
|
||||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/calls.h"
|
||||
#include "libc/calls/sig.internal.h"
|
||||
#include "libc/calls/struct/sigset.internal.h"
|
||||
#include "libc/calls/syscall-nt.internal.h"
|
||||
#include "libc/errno.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/strace.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/ctrlevent.h"
|
||||
#include "libc/nt/enum/processaccess.h"
|
||||
#include "libc/nt/errors.h"
|
||||
#include "libc/nt/memory.h"
|
||||
#include "libc/nt/process.h"
|
||||
#include "libc/nt/runtime.h"
|
||||
#include "libc/proc/proc.internal.h"
|
||||
|
@ -36,21 +41,18 @@
|
|||
textwindows int sys_kill_nt(int pid, int sig) {
|
||||
|
||||
// validate api usage
|
||||
if (!(0 <= sig && sig <= 64)) {
|
||||
if (!(0 <= sig && sig <= 64))
|
||||
return einval();
|
||||
}
|
||||
|
||||
// XXX: NT doesn't really have process groups. For instance the
|
||||
// CreateProcess() flag for starting a process group actually
|
||||
// just does an "ignore ctrl-c" internally.
|
||||
if (pid < -1) {
|
||||
if (pid < -1)
|
||||
pid = -pid;
|
||||
}
|
||||
|
||||
// no support for kill all yet
|
||||
if (pid == -1) {
|
||||
if (pid == -1)
|
||||
return einval();
|
||||
}
|
||||
|
||||
// just call raise() if we're targeting self
|
||||
if (pid <= 0 || pid == getpid()) {
|
||||
|
@ -70,6 +72,18 @@ textwindows int sys_kill_nt(int pid, int sig) {
|
|||
}
|
||||
}
|
||||
|
||||
// attempt to signal via /var/sig shared memory file
|
||||
if (pid > 0 && sig != 9) {
|
||||
atomic_ulong *sigproc;
|
||||
if ((sigproc = __sig_map_process(pid))) {
|
||||
if (sig > 0)
|
||||
atomic_fetch_or_explicit(sigproc, 1ull << (sig - 1),
|
||||
memory_order_release);
|
||||
UnmapViewOfFile(sigproc);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// find existing handle we own for process
|
||||
int64_t handle, closeme = 0;
|
||||
if (!(handle = __proc_handle(pid))) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue