Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/signal.cc')
-rw-r--r--winsup/cygwin/signal.cc481
1 files changed, 0 insertions, 481 deletions
diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
deleted file mode 100644
index 311e7303b..000000000
--- a/winsup/cygwin/signal.cc
+++ /dev/null
@@ -1,481 +0,0 @@
-/* signal.cc
-
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
-
- Written by Steve Chamberlain of Cygnus Support, sac@cygnus.com
- Significant changes by Sergey Okhapkin <sos@prospect.com.ru>
-
-This file is part of Cygwin.
-
-This software is a copyrighted work licensed under the terms of the
-Cygwin license. Please consult the file "CYGWIN_LICENSE" for
-details. */
-
-#include "winsup.h"
-#include <stdlib.h>
-#include "cygerrno.h"
-#include <sys/cygwin.h>
-#include "pinfo.h"
-#include "sigproc.h"
-#include "hires.h"
-#include "security.h"
-#include "cygtls.h"
-
-int sigcatchers; /* FIXME: Not thread safe. */
-
-#define sigtrapped(func) ((func) != SIG_IGN && (func) != SIG_DFL)
-
-static inline void
-set_sigcatchers (void (*oldsig) (int), void (*cursig) (int))
-{
-#ifdef DEBUGGING
- int last_sigcatchers = sigcatchers;
-#endif
- if (!sigtrapped (oldsig) && sigtrapped (cursig))
- sigcatchers++;
- else if (sigtrapped (oldsig) && !sigtrapped (cursig))
- sigcatchers--;
-#ifdef DEBUGGING
- if (last_sigcatchers != sigcatchers)
- sigproc_printf ("last %d, old %d, cur %p, cur %p", last_sigcatchers,
- sigcatchers, oldsig, cursig);
-#endif
-}
-
-extern "C" _sig_func_ptr
-signal (int sig, _sig_func_ptr func)
-{
- sig_dispatch_pending ();
- _sig_func_ptr prev;
-
- /* check that sig is in right range */
- if (sig < 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP)
- {
- set_errno (EINVAL);
- syscall_printf ("SIG_ERR = signal (%d, %p)", sig, func);
- return (_sig_func_ptr) SIG_ERR;
- }
-
- prev = global_sigs[sig].sa_handler;
- global_sigs[sig].sa_handler = func;
- global_sigs[sig].sa_mask = 0;
- /* SA_RESTART is set to maintain BSD compatible signal behaviour by default.
- This is also compatible with the behaviour of signal(2) in Linux. */
- global_sigs[sig].sa_flags |= SA_RESTART;
- set_sigcatchers (prev, func);
-
- syscall_printf ("%p = signal (%d, %p)", prev, sig, func);
- return prev;
-}
-
-extern "C" int
-nanosleep (const struct timespec *rqtp, struct timespec *rmtp)
-{
- int res = 0;
- sig_dispatch_pending ();
- pthread_testcancel ();
-
- if ((unsigned int) rqtp->tv_sec > (HIRES_DELAY_MAX / 1000 - 1)
- || (unsigned int) rqtp->tv_nsec > 999999999)
- {
- set_errno (EINVAL);
- return -1;
- }
- DWORD resolution = gtod.resolution ();
- DWORD req = ((rqtp->tv_sec * 1000 + (rqtp->tv_nsec + 999999) / 1000000
- + resolution - 1) / resolution) * resolution;
- DWORD end_time = gtod.dmsecs () + req;
- syscall_printf ("nanosleep (%ld)", req);
-
- int rc = pthread::cancelable_wait (signal_arrived, req);
- DWORD rem;
- if ((rem = end_time - gtod.dmsecs ()) > HIRES_DELAY_MAX)
- rem = 0;
- if (rc == WAIT_OBJECT_0)
- {
- (void) call_signal_handler_now ();
- set_errno (EINTR);
- res = -1;
- }
-
- if (rmtp)
- {
- rmtp->tv_sec = rem / 1000;
- rmtp->tv_nsec = (rem % 1000) * 1000000;
- }
-
- syscall_printf ("%d = nanosleep (%ld, %ld)", res, req, rem);
- return res;
-}
-
-extern "C" unsigned int
-sleep (unsigned int seconds)
-{
- struct timespec req, rem;
- req.tv_sec = seconds;
- req.tv_nsec = 0;
- nanosleep (&req, &rem);
- return rem.tv_sec + (rem.tv_nsec > 0);
-}
-
-extern "C" unsigned int
-usleep (unsigned int useconds)
-{
- struct timespec req;
- req.tv_sec = useconds / 1000000;
- req.tv_nsec = (useconds % 1000000) * 1000;
- int res = nanosleep (&req, 0);
- return res;
-}
-
-extern "C" int
-sigprocmask (int sig, const sigset_t *set, sigset_t *oldset)
-{
- return handle_sigprocmask (sig, set, oldset, myself->getsigmask ());
-}
-
-int __stdcall
-handle_sigprocmask (int sig, const sigset_t *set, sigset_t *oldset, sigset_t& opmask)
-{
- sig_dispatch_pending ();
- /* check that sig is in right range */
- if (sig < 0 || sig >= NSIG)
- {
- set_errno (ESRCH);
- syscall_printf ("SIG_ERR = sigprocmask signal %d out of range", sig);
- return -1;
- }
-
- if (oldset)
- {
- if (check_null_invalid_struct_errno (oldset))
- return -1;
- *oldset = opmask;
- }
-
- if (set)
- {
- if (check_invalid_read_struct_errno (set))
- return -1;
- sigset_t newmask = opmask;
- switch (sig)
- {
- case SIG_BLOCK:
- /* add set to current mask */
- newmask |= *set;
- break;
- case SIG_UNBLOCK:
- /* remove set from current mask */
- newmask &= ~*set;
- break;
- case SIG_SETMASK:
- /* just set it */
- newmask = *set;
- break;
- default:
- set_errno (EINVAL);
- return -1;
- }
- (void) set_signal_mask (newmask, opmask);
- }
- return 0;
-}
-
-static int
-kill_worker (pid_t pid, int sig)
-{
- sig_dispatch_pending ();
-
- int res = 0;
- pinfo dest (pid);
- BOOL sendSIGCONT;
-
- if (!dest)
- {
- set_errno (ESRCH);
- return -1;
- }
-
- if ((sendSIGCONT = (sig < 0)))
- sig = -sig;
-
- DWORD process_state = dest->process_state;
- if (sig == 0)
- {
- res = proc_exists (dest) ? 0 : -1;
- if (res < 0)
- set_errno (ESRCH);
- }
- else if ((res = sig_send (dest, sig)))
- {
- sigproc_printf ("%d = sig_send, %E ", res);
- res = -1;
- }
- else if (sendSIGCONT)
- (void) sig_send (dest, SIGCONT);
-
- syscall_printf ("%d = kill_worker (%d, %d), process_state %p", res, pid, sig, process_state);
- return res;
-}
-
-int
-raise (int sig)
-{
- return kill (myself->pid, sig);
-}
-
-int
-kill (pid_t pid, int sig)
-{
- syscall_printf ("kill (%d, %d)", pid, sig);
- /* check that sig is in right range */
- if (sig < 0 || sig >= NSIG)
- {
- set_errno (EINVAL);
- syscall_printf ("signal %d out of range", sig);
- return -1;
- }
-
- /* Silently ignore stop signals from a member of orphaned process group.
- FIXME: Why??? */
- if (ISSTATE (myself, PID_ORPHANED) &&
- (sig == SIGTSTP || sig == SIGTTIN || sig == SIGTTOU))
- sig = 0;
-
- return (pid > 0) ? kill_worker (pid, sig) : kill_pgrp (-pid, sig);
-}
-
-int
-kill_pgrp (pid_t pid, int sig)
-{
- int res = 0;
- int found = 0;
- int killself = 0;
-
- sigproc_printf ("pid %d, signal %d", pid, sig);
-
- winpids pids ((DWORD) PID_MAP_RW);
- for (unsigned i = 0; i < pids.npids; i++)
- {
- _pinfo *p = pids[i];
-
- if (!proc_exists (p))
- continue;
-
- /* Is it a process we want to kill? */
- 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);
- if (p == myself)
- killself++;
- else if (kill_worker (p->pid, sig))
- res = -1;
- found++;
- }
-
- if (killself && kill_worker (myself->pid, sig))
- res = -1;
-
- if (!found)
- {
- set_errno (ESRCH);
- res = -1;
- }
- syscall_printf ("%d = kill (%d, %d)", res, pid, sig);
- return res;
-}
-
-extern "C" int
-killpg (pid_t pgrp, int sig)
-{
- return kill (-pgrp, sig);
-}
-
-extern "C" void
-abort (void)
-{
- sig_dispatch_pending ();
- /* Flush all streams as per SUSv2.
- From my reading of this document, this isn't strictly correct.
- The streams are supposed to be flushed prior to exit. However,
- if there is I/O in any signal handler that will not necessarily
- be flushed.
- However this is the way FreeBSD does it, and it is much easier to
- do things this way, so... */
- if (_REENT->__cleanup)
- _REENT->__cleanup (_REENT);
-
- /* Ensure that SIGABRT can be caught regardless of blockage. */
- sigset_t sig_mask;
- sigfillset (&sig_mask);
- sigdelset (&sig_mask, SIGABRT);
- set_signal_mask (sig_mask);
-
- raise (SIGABRT);
- (void) call_signal_handler_now (); /* Call any signal handler */
- do_exit (1); /* signal handler didn't exit. Goodbye. */
-}
-
-extern "C" int
-sigaction (int sig, const struct sigaction *newact, struct sigaction *oldact)
-{
- sig_dispatch_pending ();
- sigproc_printf ("signal %d, newact %p, oldact %p", sig, newact, oldact);
- /* check that sig is in right range */
- if (sig < 0 || sig >= NSIG)
- {
- set_errno (EINVAL);
- syscall_printf ("SIG_ERR = sigaction signal %d out of range", sig);
- return -1;
- }
-
- struct sigaction oa = global_sigs[sig];
-
- if (newact)
- {
- if (sig == SIGKILL || sig == SIGSTOP)
- {
- set_errno (EINVAL);
- return -1;
- }
- global_sigs[sig] = *newact;
- if (newact->sa_handler == SIG_IGN)
- sig_clear (sig);
- if (newact->sa_handler == SIG_DFL && sig == SIGCHLD)
- sig_clear (sig);
- set_sigcatchers (oa.sa_handler, newact->sa_handler);
- if (sig == SIGCHLD)
- {
- myself->process_state &= ~PID_NOCLDSTOP;
- if (newact->sa_flags & SA_NOCLDSTOP);
- myself->process_state |= PID_NOCLDSTOP;
- }
- }
-
- if (oldact)
- *oldact = oa;
-
- return 0;
-}
-
-extern "C" int
-sigaddset (sigset_t *set, const int sig)
-{
- /* check that sig is in right range */
- if (sig <= 0 || sig >= NSIG)
- {
- set_errno (EINVAL);
- syscall_printf ("SIG_ERR = sigaddset signal %d out of range", sig);
- return -1;
- }
-
- *set |= SIGTOMASK (sig);
- return 0;
-}
-
-extern "C" int
-sigdelset (sigset_t *set, const int sig)
-{
- /* check that sig is in right range */
- if (sig <= 0 || sig >= NSIG)
- {
- set_errno (EINVAL);
- syscall_printf ("SIG_ERR = sigdelset signal %d out of range", sig);
- return -1;
- }
-
- *set &= ~SIGTOMASK (sig);
- return 0;
-}
-
-extern "C" int
-sigismember (const sigset_t *set, int sig)
-{
- /* check that sig is in right range */
- if (sig <= 0 || sig >= NSIG)
- {
- set_errno (EINVAL);
- syscall_printf ("SIG_ERR = sigdelset signal %d out of range", sig);
- return -1;
- }
-
- if (*set & SIGTOMASK (sig))
- return 1;
- else
- return 0;
-}
-
-extern "C" int
-sigemptyset (sigset_t *set)
-{
- *set = (sigset_t) 0;
- return 0;
-}
-
-extern "C" int
-sigfillset (sigset_t *set)
-{
- *set = ~((sigset_t) 0);
- return 0;
-}
-
-extern "C" int
-sigsuspend (const sigset_t *set)
-{
- return handle_sigsuspend (*set);
-}
-
-extern "C" int
-sigpause (int signal_mask)
-{
- return handle_sigsuspend ((sigset_t) signal_mask);
-}
-
-extern "C" int
-pause (void)
-{
- return handle_sigsuspend (myself->getsigmask ());
-}
-
-extern "C" int
-siginterrupt (int sig, int flag)
-{
- struct sigaction act;
- (void) sigaction(sig, NULL, &act);
- if (flag)
- act.sa_flags &= ~SA_RESTART;
- else
- act.sa_flags |= SA_RESTART;
- return sigaction (sig, &act, NULL);
-}
-
-
-extern "C" int
-sigwait (const sigset_t *set, int *sig)
-{
- pthread_testcancel ();
- _my_tls.event = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
- if (!_my_tls.event)
- {
- __seterrno ();
- return -1;
- }
-
- _my_tls.sigwait_mask = *set;
-
- switch (WaitForSingleObject (_my_tls.event, INFINITE))
- {
- case WAIT_OBJECT_0:
- CloseHandle (_my_tls.event);
- _my_tls.event = NULL;
- *sig = InterlockedExchange ((LONG *) &_my_tls.sig, (LONG) 0);
- break;
- default:
- __seterrno ();
- return -1;
- }
- return 0;
-}