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:
parent
1ef8e6c4af
commit
aafea422a5
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user