diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 6db1d52dd..f90265ddd 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,24 @@ +Wed Jan 17 09:47:13 2001 Christopher Faylor + + * autoload.cc (LoadDLLinitfunc): Remove debugging statement. + + * exceptions.cc (sig_handle_tty_stop): Move setting of PID_STOPPED to + earlier in interrupt. + ((interrupt_setup): i.e., here. + (sig_handle): Don't queue multiple SIGSTOPS. + * fhandler.h (bg_check_types): Enumerate return value of bg_check for + clarity. + * signal.cc (kill_pgrp): Minor cleanup. + * fhandler_termios.cc (fhandler_termios::bg_check): Use enumerated type + for function return. Don't raise signal if a signal is already queued. + * fhandler_console.cc (fhandler_console::read): Use enumerated return + type for bg_check. + * select.cc: Ditto, throughout. + * read.cc: Ditto, throughout. + * termios.cc: Ditto, throughout. + (_read): YA interrupt detect simplification. + * wait.cc (wait4): Ditto. + Wed Jan 17 10:56:00 2001 Corinna Vinschen * cygheap.cc (cygheap_user::~cygheap_user): Temporarily diff --git a/winsup/cygwin/autoload.cc b/winsup/cygwin/autoload.cc index 7e3dfe414..f7b0a62ef 100644 --- a/winsup/cygwin/autoload.cc +++ b/winsup/cygwin/autoload.cc @@ -106,7 +106,6 @@ LoadDLLinitfunc (ntdll) while (InterlockedIncrement (&here)) { InterlockedDecrement (&here); -small_printf ("Multiple tries to read ntdll.dll\n"); Sleep (0); } diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h index c39438ab1..69d62d2d9 100644 --- a/winsup/cygwin/cygheap.h +++ b/winsup/cygwin/cygheap.h @@ -53,7 +53,8 @@ public: const char *path () const { return root; } }; -class cygheap_user { +class cygheap_user +{ /* Extendend user information. The information is derived from the internal_getlogin call when on a NT system. */ @@ -88,12 +89,12 @@ public: PSID sid () const { return psid; } void operator =(cygheap_user &user) - { - set_name (user.name ()); - set_logsrv (user.logsrv ()); - set_domain (user.domain ()); - set_sid (user.sid ()); - } + { + set_name (user.name ()); + set_logsrv (user.logsrv ()); + set_domain (user.domain ()); + set_sid (user.sid ()); + } }; struct init_cygheap diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc index fd7de95fb..9a51f49f1 100644 --- a/winsup/cygwin/exceptions.cc +++ b/winsup/cygwin/exceptions.cc @@ -585,6 +585,27 @@ handle_sigsuspend (sigset_t tempmask) extern DWORD exec_exit; // Possible exit value for exec extern int pending_signals; +extern "C" { +static void +sig_handle_tty_stop (int sig) +{ + myself->stopsig = sig; + /* See if we have a living parent. If so, send it a special signal. + * It will figure out exactly which pid has stopped by scanning + * its list of subprocesses. + */ + if (my_parent_is_alive ()) + { + pinfo parent (myself->ppid); + sig_send (parent, __SIGCHILDSTOPPED); + } + sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p", + myself->pid, sig, myself->ppid_handle); + SuspendThread (hMainThread); + return; +} +} + int interruptible (DWORD pc, int testvalid = 0) { @@ -639,6 +660,11 @@ interrupt_setup (int sig, void *handler, DWORD retaddr, DWORD *retaddr_on_stack, sigsave.func = (void (*)(int)) handler; sigsave.sig = sig; sigsave.saved_errno = -1; // Flag: no errno to save + if (handler == sig_handle_tty_stop) + { + myself->stopsig = 0; + myself->process_state |= PID_STOPPED; + } } static bool interrupt_now (CONTEXT *, int, void *, struct sigaction&) __attribute__((regparm(3))); @@ -890,29 +916,6 @@ set_process_mask (sigset_t newmask) return; } -extern "C" { -static void -sig_handle_tty_stop (int sig) -{ - myself->stopsig = sig; - myself->process_state |= PID_STOPPED; - /* See if we have a living parent. If so, send it a special signal. - * It will figure out exactly which pid has stopped by scanning - * its list of subprocesses. - */ - if (my_parent_is_alive ()) - { - pinfo parent (myself->ppid); - sig_send (parent, __SIGCHILDSTOPPED); - } - sigproc_printf ("process %d stopped by signal %d, myself->ppid_handle %p", - myself->pid, sig, myself->ppid_handle); - /* There is a small race here with the above two mutexes */ - SuspendThread (hMainThread); - return; -} -} - int __stdcall sig_handle (int sig) { @@ -988,12 +991,15 @@ sig_handle (int sig) goto dosig; stop: + /* Eat multiple attempts to STOP */ + if (ISSTATE (myself, PID_STOPPED)) + goto done; handler = (void *) sig_handle_tty_stop; thissig = myself->getsig (SIGSTOP); dosig: /* Dispatch to the appropriate function. */ - sigproc_printf ("signal %d, about to call %p", sig, thissig.sa_handler); + sigproc_printf ("signal %d, about to call %p", sig, handler); rc = call_handler (sig, handler, thissig); done: diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 356eb6beb..92cf8c300 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -122,6 +122,14 @@ class select_record; class path_conv; class fhandler_disk_file; +enum bg_check_types +{ + bg_error = -1, + bg_eof = 0, + bg_ok = 1, + bg_signalled = 2 +}; + class fhandler_base { private: @@ -310,7 +318,7 @@ public: { return windows_device_names[FHDEVN (status)]; } - virtual int bg_check (int) {return 1;} + virtual bg_check_types bg_check (int) {return bg_ok;} void clear_readahead () { raixput = raixget = ralen = rabuflen = 0; @@ -562,7 +570,7 @@ public: int tcgetpgrp (); int tcsetpgrp (int pid); void set_ctty (int ttynum, int flags); - int bg_check (int sig); + bg_check_types bg_check (int sig); virtual DWORD __acquire_output_mutex (const char *fn, int ln, DWORD ms) {return 1;} virtual void __release_output_mutex (const char *fn, int ln) {} }; diff --git a/winsup/cygwin/fhandler_console.cc b/winsup/cygwin/fhandler_console.cc index 9030ccbe4..3af96d74a 100644 --- a/winsup/cygwin/fhandler_console.cc +++ b/winsup/cygwin/fhandler_console.cc @@ -168,7 +168,7 @@ fhandler_console::read (void *pv, size_t buflen) for (;;) { int bgres; - if ((bgres = bg_check (SIGTTIN)) <= 0) + if ((bgres = bg_check (SIGTTIN)) <= bg_eof) return bgres; set_cursor_maybe (); /* to make cursor appear on the screen immediately */ diff --git a/winsup/cygwin/fhandler_termios.cc b/winsup/cygwin/fhandler_termios.cc index 014e7d104..1d0491379 100644 --- a/winsup/cygwin/fhandler_termios.cc +++ b/winsup/cygwin/fhandler_termios.cc @@ -1,6 +1,6 @@ /* fhandler_termios.cc - Copyright 1996, 1997, 1998 Cygnus Solutions. + Copyright 1999, 2000, 2001 Red Hat, Inc. This file is part of Cygwin. @@ -107,13 +107,13 @@ fhandler_termios::set_ctty (int ttynum, int flags) } } -int +bg_check_types fhandler_termios::bg_check (int sig) { if (!myself->pgid || tc->getpgid () == myself->pgid || myself->ctty != tc->ntty || ((sig == SIGTTOU) && !(tc->ti.c_lflag & TOSTOP))) - return 1; + return bg_ok; if (sig < 0) sig = -sig; @@ -128,7 +128,7 @@ fhandler_termios::bg_check (int sig) from reallocating this pty. I think this is the case which is handled by unlockpt on a Unix system. */ termios_printf ("closed by master"); - return 0; + return bg_eof; } /* If the process group is no more or if process is ignoring or blocks 'sig', @@ -143,16 +143,19 @@ fhandler_termios::bg_check (int sig) else if (!sigs_ignored) /* nothing */; else if (sig == SIGTTOU) - return 1; /* Just allow the output */ + return bg_ok; /* Just allow the output */ else goto setEIO; /* This is an output error */ - _raise (sig); - return 1; + /* Don't raise a SIGTT* signal if we have already been interrupted + by another signal. */ + if (WaitForSingleObject (signal_arrived, 0) != WAIT_OBJECT_0) + _raise (sig); + return bg_signalled; setEIO: set_errno (EIO); - return -1; + return bg_error; } #define set_input_done(x) input_done = input_done || (x) diff --git a/winsup/cygwin/select.cc b/winsup/cygwin/select.cc index 168f92c8e..b68161dc4 100644 --- a/winsup/cygwin/select.cc +++ b/winsup/cygwin/select.cc @@ -412,7 +412,7 @@ peek_pipe (select_record *s, int ignra) gotone = 1; goto out; } - if (fh->bg_check (SIGTTIN) <= 0) + if (fh->bg_check (SIGTTIN) <= bg_eof) { gotone = s->read_ready = 1; goto out; @@ -627,7 +627,7 @@ peek_console (select_record *me, int ignra) set_handle_or_return_if_not_open (h, me); for (;;) - if (fh->bg_check (SIGTTIN) <= 0) + if (fh->bg_check (SIGTTIN) <= bg_eof) return me->read_ready = 1; else if (!PeekConsoleInput (h, &irec, 1, &events_read) || !events_read) break; diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc index 23bc9f470..c90ae6abb 100644 --- a/winsup/cygwin/signal.cc +++ b/winsup/cygwin/signal.cc @@ -213,11 +213,9 @@ kill_pgrp (pid_t pid, int sig) continue; /* Is it a process we want to kill? */ - if (pid == 0 && (p->pgid != myself->pgid || p->ctty != myself->ctty)) - continue; - if (pid > 1 && p->pgid != pid) - continue; - if (sig < 0 && NOTSTATE(p, PID_STOPPED)) + if ((pid == 0 && (p->pgid != myself->pgid || p->ctty != myself->ctty)) || + (pid > 1 && p->pgid != pid) || + (sig < 0 && NOTSTATE(p, PID_STOPPED))) continue; sigproc_printf ("killing pid %d, pgrp %d, p->ctty %d, myself->ctty %d", p->pid, p->pgid, p->ctty, myself->ctty); diff --git a/winsup/cygwin/sigproc.cc b/winsup/cygwin/sigproc.cc index 21b325dde..d7493d1be 100644 --- a/winsup/cygwin/sigproc.cc +++ b/winsup/cygwin/sigproc.cc @@ -1150,8 +1150,8 @@ wait_sig (VOID *) saw_sigchld = 1; if (sig > 0 && sig != SIGKILL && sig != SIGSTOP && - (sigismember (& myself->getsigmask (), sig) || - (sig != SIGCONT && myself->process_state & PID_STOPPED))) + (sigismember (&myself->getsigmask (), sig) || + (sig != SIGCONT && ISSTATE (myself, PID_STOPPED)))) { sigproc_printf ("sig %d blocked", sig); break; diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc index 71869cfc5..08e99cd1b 100644 --- a/winsup/cygwin/syscalls.cc +++ b/winsup/cygwin/syscalls.cc @@ -1,6 +1,6 @@ /* syscalls.cc: syscalls - Copyright 1996, 1997, 1998, 1999, 2000 Cygnus Solutions. + Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc. This file is part of Cygwin. @@ -220,8 +220,10 @@ _read (int fd, void *ptr, size_t len) { sigframe thisframe (mainthread); extern int sigcatchers; + bool sawsig; beg: + sawsig = 0; if (fdtab.not_open (fd)) { set_errno (EBADF); @@ -243,7 +245,10 @@ beg: if (!wait) set_sig_errno (EAGAIN); /* Don't really need 'set_sig_errno' here, but... */ else - set_sig_errno (EINTR); + { + set_sig_errno (EINTR); + sawsig = 1; + } res = -1; goto out; } @@ -251,7 +256,7 @@ beg: /* Check to see if this is a background read from a "tty", sending a SIGTTIN, if appropriate */ res = fh->bg_check (SIGTTIN); - if (res > 0) + if (res > bg_eof) { myself->process_state |= PID_TTYIN; res = fh->read (ptr, len); @@ -259,7 +264,7 @@ beg: } out: - if (res < 0 && get_errno () == EINTR && call_signal_handler ()) + if (sawsig && 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 ()); @@ -289,7 +294,7 @@ _write (int fd, const void *ptr, size_t len) fh = fdtab[fd]; res = fh->bg_check (SIGTTOU); - if (res > 0) + if (res > bg_eof) { myself->process_state |= PID_TTYOU; res = fh->write (ptr, len); diff --git a/winsup/cygwin/termios.cc b/winsup/cygwin/termios.cc index c72a49414..b1fd12aa8 100644 --- a/winsup/cygwin/termios.cc +++ b/winsup/cygwin/termios.cc @@ -1,6 +1,6 @@ /* termios.cc: termios for WIN32. - Copyright 1996, 1997, 1998, 2000 Cygnus Solutions. + Copyright 1996, 1997, 1998, 2000, 2001 Red Hat, Inc. Written by Doug Evans and Steve Chamberlain of Cygnus Support dje@cygnus.com, sac@cygnus.com @@ -40,7 +40,7 @@ tcsendbreak (int fd, int duration) set_errno (ENOTTY); else { - if ((res = fh->bg_check (-SIGTTOU)) > 0) + if ((res = fh->bg_check (-SIGTTOU)) > bg_eof) res = fh->tcsendbreak (duration); } @@ -70,7 +70,7 @@ tcdrain (int fd) set_errno (ENOTTY); else { - if ((res = fh->bg_check (-SIGTTOU)) > 0) + if ((res = fh->bg_check (-SIGTTOU)) > bg_eof) res = fh->tcdrain (); } @@ -98,7 +98,7 @@ tcflush (int fd, int queue) set_errno (ENOTTY); else { - if ((res = fh->bg_check (-SIGTTOU)) > 0) + if ((res = fh->bg_check (-SIGTTOU)) > bg_eof) res = fh->tcflush (queue); } @@ -126,7 +126,7 @@ tcflow (int fd, int action) set_errno (ENOTTY); else { - if ((res = fh->bg_check (-SIGTTOU)) > 0) + if ((res = fh->bg_check (-SIGTTOU)) > bg_eof) res = fh->tcflow (action); } @@ -155,7 +155,7 @@ tcsetattr (int fd, int a, const struct termios *t) set_errno (ENOTTY); else { - if ((res = fh->bg_check (-SIGTTOU)) > 0) + if ((res = fh->bg_check (-SIGTTOU)) > bg_eof) res = fh->tcsetattr (a, t); } diff --git a/winsup/cygwin/wait.cc b/winsup/cygwin/wait.cc index 852c7f453..7a106f970 100644 --- a/winsup/cygwin/wait.cc +++ b/winsup/cygwin/wait.cc @@ -51,9 +51,11 @@ wait4 (int intpid, int *status, int options, struct rusage *r) waitq *w; HANDLE waitfor; sigframe thisframe (mainthread); + bool sawsig; beg: - if (options & ~(WNOHANG | WUNTRACED)) + sawsig = 0; + if (options & ~(WNOHANG | WUNTRACED)) { set_errno (EINVAL); return -1; @@ -97,6 +99,7 @@ beg: if (w->status == -1) { set_sig_errno (EINTR); + sawsig = 1; res = -1; } else if (res != WAIT_OBJECT_0) @@ -110,7 +113,7 @@ beg: *status = w->status; done: - if (res < 0 && get_errno () == EINTR && call_signal_handler ()) + if (sawsig && call_signal_handler ()) goto beg; sigproc_printf ("intpid %d, status %p, w->status %d, options %d, res %d", intpid, status, w->status, options, res);