mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-04 18: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
|
@ -17,26 +17,10 @@
|
|||
│ PERFORMANCE OF THIS SOFTWARE. │
|
||||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/fmt/internal.h"
|
||||
#include "libc/intrin/atomic.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
|
||||
static textwindows char16_t *itoa16(char16_t p[21], uint64_t x) {
|
||||
char t;
|
||||
size_t a, b, i = 0;
|
||||
do {
|
||||
p[i++] = x % 10 + '0';
|
||||
x = x / 10;
|
||||
} while (x > 0);
|
||||
if (i) {
|
||||
for (a = 0, b = i - 1; a < b; ++a, --b) {
|
||||
t = p[a];
|
||||
p[a] = p[b];
|
||||
p[b] = t;
|
||||
}
|
||||
}
|
||||
return p + i;
|
||||
}
|
||||
|
||||
// This function is called very early by WinMain().
|
||||
textwindows char16_t *__create_pipe_name(char16_t *a) {
|
||||
char16_t *p = a;
|
||||
|
@ -44,9 +28,9 @@ textwindows char16_t *__create_pipe_name(char16_t *a) {
|
|||
static atomic_uint x;
|
||||
while (*q)
|
||||
*p++ = *q++;
|
||||
p = itoa16(p, __pid);
|
||||
p = __itoa16(p, __pid);
|
||||
*p++ = '-';
|
||||
p = itoa16(p, atomic_fetch_add(&x, 1));
|
||||
p = __itoa16(p, atomic_fetch_add(&x, 1));
|
||||
*p = 0;
|
||||
return a;
|
||||
}
|
||||
|
|
|
@ -32,12 +32,13 @@
|
|||
#include "libc/intrin/bsf.h"
|
||||
#include "libc/intrin/describebacktrace.h"
|
||||
#include "libc/intrin/dll.h"
|
||||
#include "libc/intrin/kprintf.h"
|
||||
#include "libc/intrin/maps.h"
|
||||
#include "libc/intrin/strace.h"
|
||||
#include "libc/intrin/weaken.h"
|
||||
#include "libc/nt/console.h"
|
||||
#include "libc/nt/enum/context.h"
|
||||
#include "libc/nt/enum/exceptionhandleractions.h"
|
||||
#include "libc/nt/enum/processcreationflags.h"
|
||||
#include "libc/nt/enum/signal.h"
|
||||
#include "libc/nt/enum/status.h"
|
||||
#include "libc/nt/events.h"
|
||||
|
@ -46,6 +47,7 @@
|
|||
#include "libc/nt/struct/ntexceptionpointers.h"
|
||||
#include "libc/nt/synchronization.h"
|
||||
#include "libc/nt/thread.h"
|
||||
#include "libc/runtime/internal.h"
|
||||
#include "libc/runtime/symbols.internal.h"
|
||||
#include "libc/str/str.h"
|
||||
#include "libc/sysv/consts/sa.h"
|
||||
|
@ -58,6 +60,8 @@
|
|||
* @fileoverview Cosmopolitan Signals for Windows.
|
||||
*/
|
||||
|
||||
#define STKSZ 65536
|
||||
|
||||
struct SignalFrame {
|
||||
unsigned rva;
|
||||
unsigned flags;
|
||||
|
@ -80,7 +84,7 @@ textwindows bool __sig_ignored(int sig) {
|
|||
|
||||
textwindows void __sig_delete(int sig) {
|
||||
struct Dll *e;
|
||||
atomic_fetch_and_explicit(&__sig.pending, ~(1ull << (sig - 1)),
|
||||
atomic_fetch_and_explicit(__sig.process, ~(1ull << (sig - 1)),
|
||||
memory_order_relaxed);
|
||||
_pthread_lock();
|
||||
for (e = dll_last(_pthread_list); e; e = dll_prev(_pthread_list, e))
|
||||
|
@ -108,7 +112,7 @@ static textwindows int __sig_getter(atomic_ulong *sigs, sigset_t masked) {
|
|||
textwindows int __sig_get(sigset_t masked) {
|
||||
int sig;
|
||||
if (!(sig = __sig_getter(&__get_tls()->tib_sigpending, masked)))
|
||||
sig = __sig_getter(&__sig.pending, masked);
|
||||
sig = __sig_getter(__sig.process, masked);
|
||||
return sig;
|
||||
}
|
||||
|
||||
|
@ -179,6 +183,7 @@ textwindows int __sig_raise(volatile int sig, int sic) {
|
|||
unsigned rva, flags;
|
||||
struct PosixThread *pt = _pthread_self();
|
||||
if (__sig_start(pt, sig, &rva, &flags)) {
|
||||
|
||||
if (flags & SA_RESETHAND) {
|
||||
STRACE("resetting %G handler", sig);
|
||||
__sighandrvas[sig] = (int32_t)(intptr_t)SIG_DFL;
|
||||
|
@ -410,7 +415,7 @@ textwindows void __sig_generate(int sig, int sic) {
|
|||
STRACE("terminating on %G due to no handler", sig);
|
||||
__sig_terminate(sig);
|
||||
}
|
||||
if (atomic_load_explicit(&__sig.pending, memory_order_acquire) &
|
||||
if (atomic_load_explicit(__sig.process, memory_order_acquire) &
|
||||
(1ull << (sig - 1))) {
|
||||
return;
|
||||
}
|
||||
|
@ -448,7 +453,7 @@ textwindows void __sig_generate(int sig, int sic) {
|
|||
__sig_killer(mark, sig, sic);
|
||||
_pthread_unref(mark);
|
||||
} else {
|
||||
atomic_fetch_or_explicit(&__sig.pending, 1ull << (sig - 1),
|
||||
atomic_fetch_or_explicit(__sig.process, 1ull << (sig - 1),
|
||||
memory_order_relaxed);
|
||||
}
|
||||
ALLOW_SIGNALS;
|
||||
|
@ -611,11 +616,28 @@ textwindows int __sig_check(void) {
|
|||
}
|
||||
}
|
||||
|
||||
// delivers signals from other processes asynchronously
|
||||
textwindows dontinstrument static uint32_t __sig_worker(void *arg) {
|
||||
struct CosmoTib tls;
|
||||
__bootstrap_tls(&tls, __builtin_frame_address(0));
|
||||
char *sp = __builtin_frame_address(0);
|
||||
__maps_track((char *)(((uintptr_t)sp + __pagesize - 1) & -__pagesize) - STKSZ,
|
||||
STKSZ);
|
||||
for (;;) {
|
||||
int sig;
|
||||
if ((sig = __sig_getter(__sig.process, 0)))
|
||||
__sig_generate(sig, SI_KERNEL);
|
||||
Sleep(1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((__constructor__(10))) textstartup void __sig_init(void) {
|
||||
if (!IsWindows())
|
||||
return;
|
||||
AddVectoredExceptionHandler(true, (void *)__sig_crash);
|
||||
SetConsoleCtrlHandler((void *)__sig_console, true);
|
||||
CreateThread(0, STKSZ, __sig_worker, 0, kNtStackSizeParamIsAReservation, 0);
|
||||
}
|
||||
|
||||
#endif /* __x86_64__ */
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#ifndef COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
|
||||
#define COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_
|
||||
#include "libc/atomic.h"
|
||||
#include "libc/calls/struct/sigset.h"
|
||||
#include "libc/thread/posixthread.internal.h"
|
||||
|
||||
|
@ -9,8 +10,8 @@
|
|||
COSMOPOLITAN_C_START_
|
||||
|
||||
struct Signals {
|
||||
_Atomic(uint64_t) pending;
|
||||
_Atomic(uint64_t) count;
|
||||
atomic_ulong *process;
|
||||
atomic_ulong count;
|
||||
};
|
||||
|
||||
extern struct Signals __sig;
|
||||
|
@ -27,5 +28,8 @@ void __sig_delete(int);
|
|||
void __sig_generate(int, int);
|
||||
void __sig_init(void);
|
||||
|
||||
char16_t *__sig_process_path(char16_t *, uint32_t);
|
||||
atomic_ulong *__sig_map_process(int);
|
||||
|
||||
COSMOPOLITAN_C_END_
|
||||
#endif /* COSMOPOLITAN_LIBC_CALLS_SIGNALS_INTERNAL_H_ */
|
||||
|
|
|
@ -53,7 +53,7 @@ int sigpending(sigset_t *pending) {
|
|||
}
|
||||
rc = 0;
|
||||
} else if (IsWindows()) {
|
||||
*pending = atomic_load_explicit(&__sig.pending, memory_order_acquire) |
|
||||
*pending = atomic_load_explicit(__sig.process, memory_order_acquire) |
|
||||
atomic_load_explicit(&__get_tls()->tib_sigpending,
|
||||
memory_order_acquire);
|
||||
rc = 0;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue