*sigpause hanging on 8.x+

Garrett Cooper yanegomi at gmail.com
Sun Jul 11 19:39:40 UTC 2010

So, long story short... I've basically ported the open posix testsuite
to FreeBSD, and one of the tests tests out sigpause. Unfortunately the
sucker hangs on my dev box at home.

I've written a short testcase that demonstrates this. It prints out:

$ ~/test_sigpause

And proceeds to be unresponsive to signals (except SIGSTOP / SIGKILL,
as expected).

When I monkey around with libc's compat4.3 stuff a bit, this is what comes up:

$ env LD_LIBRARY_PATH=$PWD:/usr/src/lib/libc/../libthr ~/test_sigpause
before sigemptyset
before _sigsuspend

So it's getting stuck after calling _sigsuspend.

I tried the same thing on a i386 8-STABLE VM and it hangs as well.

I tried applying similar printfs in libthr but it's not hitting that
code at all (it's now responding to SIGTERM though, which is
interesting, but not too interesting to me).

I also wrote similar code that exercised the functionality in
sigsuspend, by calling sigprocmask beforehand, and it works.



Dev machine:
FreeBSD bayonetta.local 9.0-CURRENT FreeBSD 9.0-CURRENT #1
r206173:209901M: Sun Jul 11 04:18:42 PDT 2010
root@:/usr/obj/usr/src/sys/BAYONETTA  amd64
FreeBSD starr-bastion.localdomain 8.0-STABLE FreeBSD 8.0-STABLE #0
r207913: Tue May 11 06:21:57 UTC 2010
root at starr-bastion.localdomain:/usr/obj/usr/src/sys/GENERIC  i386

Index: compat-43/sigcompat.c
--- compat-43/sigcompat.c	(revision 206173)
+++ compat-43/sigcompat.c	(working copy)
@@ -36,6 +36,7 @@
 #include "namespace.h"
 #include <sys/param.h>
 #include <signal.h>
+#include <stdio.h>
 #include <string.h>
 #include "un-namespace.h"
 #include "libc_private.h"
@@ -102,7 +103,9 @@
 	sigset_t set;

+	printf("before sigemptyset\n");
+	printf("before _sigsuspend\n");
 	set.__bits[0] = mask;
 	return (_sigsuspend(&set));
@@ -111,10 +114,16 @@
 xsi_sigpause(int sig)
 	sigset_t set;
+	int rc;

+	printf("before sigemptyset\n");
+	printf("before sigaddset\n");
 	sigaddset(&set, sig);
-	return (_sigsuspend(&set));
+	printf("before _sigsuspend\n");
+	rc = (_sigsuspend(&set));
+	printf("after _sigsuspend\n");
+	return rc;


$ cat ~/test_sigpause.c
#include <signal.h>
#include <stdio.h>

main (void)
        (void) sigpause(1);
        return 0;
$ cat ~/test_sigsuspend.c
#include <err.h>
#include <signal.h>

main (void)
        sigset_t oset;
        sigset_t nset;
        if (sigprocmask(1, &nset, &oset) == -1)
                err(1, "sigprocmask(-1, &nset, &oset)");
        if (sigprocmask(-1, &nset, &oset) == -1)
                err(1, "sigprocmask(-1, &nset, &oset)");
        return (sigsuspend(&nset));

More information about the freebsd-hackers mailing list