Make sigpending and sigsuspend account for signals that are pending on

the process as well as pending on the current thread.

Reported by:	Andrew MacIntyre <andymac@bullseye.apana.org.au>
This commit is contained in:
deischen 2002-06-28 13:28:41 +00:00
parent 1ef8e6c4af
commit aafea422a5
6 changed files with 81 additions and 15 deletions

View File

@ -31,6 +31,9 @@
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/signalvar.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
@ -39,9 +42,9 @@
__weak_reference(_sigpending, sigpending);
int
_sigpending(sigset_t * set)
_sigpending(sigset_t *set)
{
struct pthread *curthread = _get_curthread();
struct pthread *curthread = _get_curthread();
int ret = 0;
/* Check for a null signal set pointer: */
@ -51,6 +54,7 @@ _sigpending(sigset_t * set)
}
else {
*set = curthread->sigpend;
SIGSETOR(*set, _process_sigpending);
}
/* Return the completion status: */
return (ret);

View File

@ -32,6 +32,8 @@
* $FreeBSD$
*/
#include <signal.h>
#include <sys/param.h>
#include <sys/signalvar.h>
#include <errno.h>
#include <pthread.h>
#include "pthread_private.h"
@ -43,7 +45,7 @@ _sigsuspend(const sigset_t * set)
{
struct pthread *curthread = _get_curthread();
int ret = -1;
sigset_t oset;
sigset_t oset, sigset;
/* Check if a new signal set was provided by the caller: */
if (set != NULL) {
@ -53,8 +55,24 @@ _sigsuspend(const sigset_t * set)
/* Change the caller's mask: */
curthread->sigmask = *set;
/* Wait for a signal: */
_thread_kern_sched_state(PS_SIGSUSPEND, __FILE__, __LINE__);
/*
* Check if there are pending signals for the running
* thread or process that aren't blocked:
*/
sigset = curthread->sigpend;
SIGSETOR(sigset, _process_sigpending);
SIGSETNAND(sigset, curthread->sigmask);
if (SIGNOTEMPTY(sigset)) {
/*
* Call the kernel scheduler which will safely
* install a signal frame for the running thread:
*/
_thread_kern_sched_sig();
} else {
/* Wait for a signal: */
_thread_kern_sched_state(PS_SIGSUSPEND,
__FILE__, __LINE__);
}
/* Always return an interrupted error: */
errno = EINTR;

View File

@ -31,6 +31,9 @@
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/signalvar.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
@ -39,9 +42,9 @@
__weak_reference(_sigpending, sigpending);
int
_sigpending(sigset_t * set)
_sigpending(sigset_t *set)
{
struct pthread *curthread = _get_curthread();
struct pthread *curthread = _get_curthread();
int ret = 0;
/* Check for a null signal set pointer: */
@ -51,6 +54,7 @@ _sigpending(sigset_t * set)
}
else {
*set = curthread->sigpend;
SIGSETOR(*set, _process_sigpending);
}
/* Return the completion status: */
return (ret);

View File

@ -32,6 +32,8 @@
* $FreeBSD$
*/
#include <signal.h>
#include <sys/param.h>
#include <sys/signalvar.h>
#include <errno.h>
#include <pthread.h>
#include "pthread_private.h"
@ -43,7 +45,7 @@ _sigsuspend(const sigset_t * set)
{
struct pthread *curthread = _get_curthread();
int ret = -1;
sigset_t oset;
sigset_t oset, sigset;
/* Check if a new signal set was provided by the caller: */
if (set != NULL) {
@ -53,8 +55,24 @@ _sigsuspend(const sigset_t * set)
/* Change the caller's mask: */
curthread->sigmask = *set;
/* Wait for a signal: */
_thread_kern_sched_state(PS_SIGSUSPEND, __FILE__, __LINE__);
/*
* Check if there are pending signals for the running
* thread or process that aren't blocked:
*/
sigset = curthread->sigpend;
SIGSETOR(sigset, _process_sigpending);
SIGSETNAND(sigset, curthread->sigmask);
if (SIGNOTEMPTY(sigset)) {
/*
* Call the kernel scheduler which will safely
* install a signal frame for the running thread:
*/
_thread_kern_sched_sig();
} else {
/* Wait for a signal: */
_thread_kern_sched_state(PS_SIGSUSPEND,
__FILE__, __LINE__);
}
/* Always return an interrupted error: */
errno = EINTR;

View File

@ -31,6 +31,9 @@
*
* $FreeBSD$
*/
#include <sys/param.h>
#include <sys/types.h>
#include <sys/signalvar.h>
#include <signal.h>
#include <errno.h>
#include <pthread.h>
@ -39,9 +42,9 @@
__weak_reference(_sigpending, sigpending);
int
_sigpending(sigset_t * set)
_sigpending(sigset_t *set)
{
struct pthread *curthread = _get_curthread();
struct pthread *curthread = _get_curthread();
int ret = 0;
/* Check for a null signal set pointer: */
@ -51,6 +54,7 @@ _sigpending(sigset_t * set)
}
else {
*set = curthread->sigpend;
SIGSETOR(*set, _process_sigpending);
}
/* Return the completion status: */
return (ret);

View File

@ -32,6 +32,8 @@
* $FreeBSD$
*/
#include <signal.h>
#include <sys/param.h>
#include <sys/signalvar.h>
#include <errno.h>
#include <pthread.h>
#include "pthread_private.h"
@ -43,7 +45,7 @@ _sigsuspend(const sigset_t * set)
{
struct pthread *curthread = _get_curthread();
int ret = -1;
sigset_t oset;
sigset_t oset, sigset;
/* Check if a new signal set was provided by the caller: */
if (set != NULL) {
@ -53,8 +55,24 @@ _sigsuspend(const sigset_t * set)
/* Change the caller's mask: */
curthread->sigmask = *set;
/* Wait for a signal: */
_thread_kern_sched_state(PS_SIGSUSPEND, __FILE__, __LINE__);
/*
* Check if there are pending signals for the running
* thread or process that aren't blocked:
*/
sigset = curthread->sigpend;
SIGSETOR(sigset, _process_sigpending);
SIGSETNAND(sigset, curthread->sigmask);
if (SIGNOTEMPTY(sigset)) {
/*
* Call the kernel scheduler which will safely
* install a signal frame for the running thread:
*/
_thread_kern_sched_sig();
} else {
/* Wait for a signal: */
_thread_kern_sched_state(PS_SIGSUSPEND,
__FILE__, __LINE__);
}
/* Always return an interrupted error: */
errno = EINTR;