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.cc551
1 files changed, 0 insertions, 551 deletions
diff --git a/winsup/cygwin/signal.cc b/winsup/cygwin/signal.cc
deleted file mode 100644
index bd75dff32..000000000
--- a/winsup/cygwin/signal.cc
+++ /dev/null
@@ -1,551 +0,0 @@
-/* signal.cc
-
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 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) _my_tls.call_signal_handler ();
- 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 (EINVAL);
- syscall_printf ("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, siginfo_t& si)
-{
- sig_dispatch_pending ();
-
- int res = 0;
- pinfo dest (pid);
- bool sendSIGCONT;
-
- if (!dest)
- {
- set_errno (ESRCH);
- return -1;
- }
-
- if ((sendSIGCONT = (si.si_signo < 0)))
- si.si_signo = -si.si_signo;
-
- DWORD process_state = dest->process_state;
- if (si.si_signo == 0)
- {
- res = proc_exists (dest) ? 0 : -1;
- if (res < 0)
- set_errno (ESRCH);
- }
- else if ((res = sig_send (dest, si)))
- {
- sigproc_printf ("%d = sig_send, %E ", res);
- res = -1;
- }
- else if (sendSIGCONT)
- {
- siginfo_t si2;
- si2.si_signo = SIGCONT;
- si2.si_code = SI_KERNEL;
- si2.si_pid = si2.si_uid = si2.si_errno = 0;
- (void) sig_send (dest, si2);
- }
-
- syscall_printf ("%d = kill_worker (%d, %d), process_state %p", res, pid,
- si.si_signo, process_state);
- return res;
-}
-
-int
-raise (int sig)
-{
- return kill (myself->pid, sig);
-}
-
-static int
-kill0 (pid_t pid, siginfo_t& si)
-{
- syscall_printf ("kill (%d, %d)", pid, si.si_signo);
- /* check that sig is in right range */
- if (si.si_signo < 0 || si.si_signo >= NSIG)
- {
- set_errno (EINVAL);
- syscall_printf ("signal %d out of range", si.si_signo);
- return -1;
- }
-
- /* Silently ignore stop signals from a member of orphaned process group.
- FIXME: Why??? */
- if (ISSTATE (myself, PID_ORPHANED) &&
- (si.si_signo == SIGTSTP || si.si_signo == SIGTTIN || si.si_signo == SIGTTOU))
- si.si_signo = 0;
-
- return (pid > 0) ? kill_worker (pid, si) : kill_pgrp (-pid, si);
-}
-
-int
-killsys (pid_t pid, int sig)
-{
- siginfo_t si;
- si.si_signo = sig;
- si.si_code = SI_KERNEL;
- si.si_pid = si.si_uid = si.si_errno = 0;
- return kill0 (pid, si);
-}
-int
-kill (pid_t pid, int sig)
-{
- siginfo_t si;
- si.si_signo = sig;
- si.si_code = SI_USER;
- si.si_pid = si.si_uid = si.si_errno = 0;
- return kill0 (pid, si);
-}
-
-int
-kill_pgrp (pid_t pid, siginfo_t& si)
-{
- int res = 0;
- int found = 0;
- int killself = 0;
-
- sigproc_printf ("pid %d, signal %d", pid, si.si_signo);
-
- 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) ||
- (si.si_signo < 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, si))
- res = -1;
- found++;
- }
-
- if (killself && !exit_state && kill_worker (myself->pid, si))
- res = -1;
-
- if (!found)
- {
- set_errno (ESRCH);
- res = -1;
- }
- syscall_printf ("%d = kill (%d, %d)", res, pid, si.si_signo);
- 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) _my_tls.call_signal_handler (); /* 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 ();
- /* check that sig is in right range */
- if (sig < 0 || sig >= NSIG)
- {
- set_errno (EINVAL);
- sigproc_printf ("signal %d, newact %p, oldact %p", sig, newact, oldact);
- syscall_printf ("SIG_ERR = sigaction signal %d out of range", sig);
- return -1;
- }
-
- struct sigaction oa = global_sigs[sig];
-
- if (newact)
- sigproc_printf ("signal %d, newact %p (handler %p), oa %p", sig, newact, newact->sa_handler, oa, oa.sa_handler);
- else
- sigproc_printf ("signal %d, newact %p, oa %p", sig, newact, oa, oa.sa_handler);
-
- 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_ptr)
-{
- int sig = sigwaitinfo (set, NULL);
- if (sig > 0)
- *sig_ptr = sig;
- return sig > 0 ? 0 : -1;
-}
-
-extern "C" int
-sigwaitinfo (const sigset_t *set, siginfo_t *info)
-{
- pthread_testcancel ();
- HANDLE h;
- h = _my_tls.event = CreateEvent (&sec_none_nih, FALSE, FALSE, NULL);
- if (!h)
- {
- __seterrno ();
- return -1;
- }
-
- _my_tls.sigwait_mask = *set;
- sig_dispatch_pending (true);
-
- int res;
- switch (WaitForSingleObject (h, INFINITE))
- {
- case WAIT_OBJECT_0:
- if (!sigismember (set, _my_tls.infodata.si_signo))
- {
- set_errno (EINTR);
- res = -1;
- }
- else
- {
- if (info)
- *info = _my_tls.infodata;
- res = _my_tls.infodata.si_signo;
- InterlockedExchange ((LONG *) &_my_tls.sig, (LONG) 0);
- }
- break;
- default:
- __seterrno ();
- res = -1;
- }
- CloseHandle (h);
- sigproc_printf ("returning sig %d", res);
- return res;
-}
-
-extern "C" int
-sigqueue (pid_t pid, int sig, const union sigval value)
-{
- siginfo_t si;
- pinfo dest (pid);
- if (!dest)
- {
- set_errno (ESRCH);
- return -1;
- }
- si.si_signo = sig;
- si.si_code = SI_USER;
- si.si_pid = si.si_uid = si.si_errno = 0;
- si.si_value = value;
- return sig_send (dest, si);
-}