diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index a44049f91..506f5229c 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,17 @@ +Fri Jan 12 00:35:15 2001 Christopher Faylor + + * debug.h: Add regparm attributes to some functions. + + * signal.cc (sigaction): Don't treat SIGCONT specially. + + * exceptions.cc (interrupt_setup): Save sa_flags of interrupted signal for later use. + (sig_handler): Default any stopping signal to SIGSTOP. + (call_signal_handler): New function. + (sigdelayed0): New function. + * sigproc.cc (sigproc_init): Initialize SIGSTOP sigaction for special behavior. + * sigproc.h: Define call_signal_handler. + * syscalls.cc (_read): Allow restartable signal behavior. + Thu Jan 11 13:17:00 2001 Corinna Vinschen * fhandler.h (fhandler_base): New method `fixup_mmap_after_fork'. diff --git a/winsup/cygwin/debug.h b/winsup/cygwin/debug.h index ff4313f77..2f06286c7 100644 --- a/winsup/cygwin/debug.h +++ b/winsup/cygwin/debug.h @@ -27,9 +27,9 @@ DWORD __stdcall WFMO (DWORD, CONST HANDLE *, BOOL, DWORD) __attribute__ ((regpar #define _DEBUG_H_ void threadname_init (); -HANDLE __stdcall makethread (LPTHREAD_START_ROUTINE, LPVOID, DWORD, const char *); -const char * __stdcall threadname (DWORD, int lockit = TRUE); -void __stdcall regthread (const char *, DWORD); +HANDLE __stdcall makethread (LPTHREAD_START_ROUTINE, LPVOID, DWORD, const char *) __attribute__ ((regparm(3))); +const char * __stdcall threadname (DWORD, int lockit = TRUE) __attribute__ ((regparm(2))); +void __stdcall regthread (const char *, DWORD) __attribute__ ((regparm(1))); int __stdcall iscygthread (); #ifndef DEBUGGING diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index c053cd938..fd7de95fb 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -31,6 +31,7 @@ extern "C" { static int handle_exceptions (EXCEPTION_RECORD *, void *, CONTEXT *, void *); extern void sigreturn (); extern void sigdelayed (); +extern void sigdelayed0 (); extern void siglast (); extern DWORD __no_sig_start, __no_sig_end; }; @@ -634,6 +635,7 @@ interrupt_setup (int sig, void *handler, DWORD retaddr, DWORD *retaddr_on_stack, sigsave.oldmask = myself->getsigmask (); // Remember for restoration /* FIXME: Not multi-thread aware */ sigsave.newmask = myself->getsigmask () | siga.sa_mask | SIGTOMASK (sig); + sigsave.sa_flags = siga.sa_flags; sigsave.func = (void (*)(int)) handler; sigsave.sig = sig; sigsave.saved_errno = -1; // Flag: no errno to save @@ -987,6 +989,7 @@ sig_handle (int sig) stop: handler = (void *) sig_handle_tty_stop; + thissig = myself->getsig (SIGSTOP); dosig: /* Dispatch to the appropriate function. */ @@ -1091,6 +1094,16 @@ reset_signal_arrived () sigproc_printf ("reset signal_arrived"); } +int __stdcall +call_signal_handler () +{ + int sa_flags = sigsave.sa_flags; + sigproc_printf ("sa_flags %p", sa_flags); + *sigsave.retaddr_on_stack = sigsave.retaddr; + sigdelayed0 (); + return sa_flags & SA_RESTART; +} + void unused_sig_wrapper () { /* Signal cleanup stuff. Cleans up stack (too bad that we didn't @@ -1123,6 +1136,7 @@ _sigreturn: __no_sig_start: _sigdelayed: pushl %2 # original return address +_sigdelayed0: pushl %%ebp movl %%esp,%%ebp pushf diff --git a/winsup/cygwin/perthread.h b/winsup/cygwin/perthread.h index 89b97d4fb..889a5d8c4 100644 --- a/winsup/cygwin/perthread.h +++ b/winsup/cygwin/perthread.h @@ -1,6 +1,6 @@ /* perthread.h: Header file for cygwin synchronization primitives. - Copyright 2000 Cygnus Solutions. + Copyright 2000, 2001 Red Hat, Inc. Written by Christopher Faylor @@ -96,6 +96,7 @@ struct signal_dispatch void (*func) (int); int sig; int saved_errno; + int sa_flags; DWORD oldmask; DWORD newmask; DWORD retaddr; diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index f1a5131e1..23bc9f470 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -262,8 +262,7 @@ sigaction (int sig, const struct sigaction *newact, struct sigaction *oldact) if (newact) { - if ((sig == SIGKILL || sig == SIGSTOP || sig == SIGCONT) && - newact->sa_handler != SIG_DFL) + if ((sig == SIGKILL || sig == SIGSTOP) && newact->sa_handler != SIG_DFL) { set_errno (EINVAL); return -1; diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index ceea74833..21b325dde 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -562,6 +562,7 @@ sigproc_init () } memset (w, 0, sizeof *w); // Just to be safe + myself->getsig (SIGSTOP).sa_flags = SA_RESTART | SA_NODEFER; sigproc_printf ("process/signal handling enabled(%x)", myself->process_state); return; } diff --git a/winsup/cygwin/sigproc.h b/winsup/cygwin/sigproc.h index 6e471dd2f..a5b72bca2 100644 --- a/winsup/cygwin/sigproc.h +++ b/winsup/cygwin/sigproc.h @@ -98,6 +98,7 @@ BOOL __stdcall pid_exists (pid_t) __attribute__ ((regparm(1))); int __stdcall sig_send (_pinfo *, int, DWORD ebp = (DWORD) __builtin_frame_address (0)) __attribute__ ((regparm(3))); void __stdcall signal_fixup_after_fork (); void __stdcall signal_fixup_after_exec (bool); +extern "C" int __stdcall call_signal_handler (); extern char myself_nowait_dummy[]; extern char myself_nowait_nonmain_dummy[]; diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 1cf7d6284..0f6834422 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -220,6 +220,8 @@ _read (int fd, void *ptr, size_t len) { sigframe thisframe (mainthread); extern int sigcatchers; + +beg: if (fdtab.not_open (fd)) { set_errno (EBADF); @@ -257,8 +259,11 @@ _read (int fd, void *ptr, size_t len) } out: - syscall_printf ("%d = read (%d<%s>, %p, %d), errno %d", res, fd, fh->get_name (), - ptr, len, get_errno ()); + if (res < 0 && WaitForSingleObject (signal_arrived, 0) == WAIT_OBJECT_0 && + call_signal_handler ()) + goto beg; + syscall_printf ("%d = read (%d<%s>, %p, %d), bin %d, errno %d", res, fd, fh->get_name (), + ptr, len, fh->get_r_binary (), get_errno ()); MALLOC_CHECK; return res; }