Skip site navigation (1)Skip section navigation (2)
Date:      Wed, 15 Apr 1998 20:49:28 +0100
From:      James Raynard <fhackers@jraynard.demon.co.uk>
To:        rotel@indigo.ie
Cc:        joelh@gnu.org, freebsd-hackers@FreeBSD.ORG
Subject:   Re: PR kern/1144
Message-ID:  <19980415204928.43540@jraynard.demon.co.uk>
In-Reply-To: <199804150103.CAA01392@indigo.ie>; from Niall Smart on Wed, Apr 15, 1998 at 02:03:43AM %2B0000
References:  <fhackers@jraynard.demon.co.uk> <199804150103.CAA01392@indigo.ie>

next in thread | previous in thread | raw e-mail | index | archive | help
On Wed, Apr 15, 1998 at 02:03:43AM +0000, Niall Smart wrote:
> On Apr 1n,  9:17pm, James Raynard wrote:
> > 
> > In his reply to my original PR, bde posted a macro that did what you
> > suggest for integer arguments (is this not in the PR database?).
> 
> Nope.  Still got it?

Yep.  Note there's a followup as well.

James

Date: Tue, 16 Apr 1996 19:20:07 +1000
From: Bruce Evans <bde@zeta.org.au>
Subject: Re:  kern/1144: sig{add, del}set and sigismember fns don't check signo

> >Obviously the macros would be much harder to fix
> 
> Would they?  How about
> 
> #define sigaddset(set, signo)   (((signo) <= 0 || (signo) >= NSIG) ?
> 					(errno = EINVAL, -1) :
> 					(*(set) |= 1 << ((signo) - 1), 0))
> 
> (untested, as usual)

Try it with:

	for (signo = 0; signo < 32; )
		sigaddset(set, signo++);

or weird and not so weird things like:

	void *s = set;
	sigaddset(set, 1.234);
	sigaddset(s, SIGINT);

which also fail for the standard macro, but would work for a prototyped
function.

It is possible to write it as a safe macro using Gnu C:

#define sigaddset(set, signo)					\
	({ struct sigaction *__set = set;			\
	   int __signo = (signo);				\
	   int __rv;						\
								\
	   /* 32 because NSIG is in application namespace. */	\
	   if (__signo <= 0 || __signo >= 32) {			\
	   	errno = EINVAL;					\
	   	__rv = -1;					\
	   } else {						\
		*__set |= 1 << __signo;				\
		__rv = 0;					\
	   }							\
	   __rv; })

Untested, as usual.

Who wants all that for a function?  It is probably a pessimization to
inline it unless signo is a constant.  A larger and uglier gcc macro
could be used to handle the constant case inline and call a function
otherwise.  Linux once used inline versions, but switched to function
versions because the macros aren't worth the trouble.

POSIX.1 1990 is unclearly written in this area.  I think it allows our
current macros for everything except sigismember().  It doesn't
explictly require detection of errors, but it requires sigismember() to
either fail and return -1 or succeed and return a value other than 0 if
the signal isn't a member of the set.  This fits well with most uses of
the macros - you check the signal number using sigismember(), or know
that it is valid, and then checking it in the other macros is a waste of
time.

Bruce

Date: Tue, 16 Apr 1996 22:37:47 +1000
From: Bruce Evans <bde@zeta.org.au>
Subject: Re:  kern/1144: sig{add, del}set and sigismember fns don't check signo

I wrote:

>#define sigaddset(set, signo)					\
>	({ struct sigaction *__set = set;			\
>	   int __signo = (signo);				\
>	   int __rv;						\
>								\
>	   /* 32 because NSIG is in application namespace. */	\
>	   if (__signo <= 0 || __signo >= 32) {			\
>	   	errno = EINVAL;					\

Namespace stuff is tricky.  I think EINVAL isn't supposed to be
visible if only <signal.h> is included, so it can't be used
directly.

Bruce


To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-hackers" in the body of the message



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?19980415204928.43540>