Subject: Problems with sigismember macro?

From: [email-masked]

I was trying to compile up cvs today using the Aug. 1 binary snapshot.
It compiles ok after some tweaking but would just go into an infinite
loop when run.

This code is what was causing it:

        (void) sigfillset(&sigset_test);
        for (i = 1; sigismember(&sigset_test, i) == 1; i++)
                ;

Basically it's trying a brute force method to determine the largest valid
signal number presuming they are in sequence. Now this works perfectly fine
if I add a #undef sigismember above that to make sure it uses the
library call. The reason it breaks, if the macro from <signal.h> is :

#define sigismember(set, signo) ((*(set) & (1 << ((signo) - 1))) != 0)

This won't work because sigismember is supposed to return -1 on error's such
as invalid arguments and such. It's also supposed to return 0 on signals
that aren't set in the mask. Since signo is getting passed in values that
are larger than 32 (the number of bits in an int) the results from
that shift are just undefined and from what I can see always return true.

My suggestion here is to just remove the sigismember macro since it can't
possibly do everything sigismember is supposed to do. The other sig macro's
look fine however.

James

---

From: [email-masked] (J.T. Conklin)

> It compiles ok after some tweaking but would just go into an infinite

This has been discussed quite a bit on the mailing lists.  To summarize:
NetBSD's sigismember() macro was POSIX compliant, an implementation is
permited to not detect errors; CVS is relying on non-portable behavior; we
got tired of definding NetBSD's behavior each time someone tried to
compile CVS; so we gave up and removed the sigaddset, sigdelset and 
sigismember macros.  I don't remember the exact date they were removed, 
but they will be gone when you upgrade your source.

If you are interested, you can look up the details in the NetBSD mailing 
list archives.

	--jtc

---

From: Mark Gooderum <[email-masked]>

I believe this was done already...I recall a discussion on this.

BTW...if you want to write portable code, this idiom *doesn't* work.
And I don't mean sigismember() problems...

An invalid signal number doesn't mean you're past the valid signal number.

Your best bet is using NSIG or picking some arbirtrary maximum, and if you
really care, keeping a mask of valid signals.

Solaris 2.3 and 2.4 are examples of OS's where this isn't true (there
are others though)...the signals go up to about 33, then skip into a
higher range.  There are also signals that are only valid for your
process if you are realtime versus timesharing.

Finally, even the function sigismember() isn't a way to determine if a 
signal is valid, it will still typically run and work through to some
maximum (NSIG-1 often), even though there may be holes in this range.
To determine truely valid signal numbers, you have to invoke something
like sigaction() that calls the OS to be sure.

Also, some programs decide to be cute and catch all signals.  This 
isn't safe either...if you do it on Solaris 2.3/2.4 (again), you'll 
never block on a signal because you are handling SIGLWP...which is sent
when all your LWPs are blocked...fun.

These minor bits may not matter to you, but they might, so I'm sharing them
from the experience of porting some serious systems level code to things
as diverse as AIX, Solaris, SunOS, DG/UX, and more...don't even ask me
about restartable system calls on HP/UX...

-Mark

---

From: [email-masked]

>really care, keeping a mask of valid signals.

Oh, I'm not saying the cvs code was good by any means, just that there was
no way for the macro to generate the proper output in any case.

I don't program that way :-)

James