Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

signalfd() not handling sigqueue() sigval data correctly

29 views
Skip to first unread message

Michael Kerrisk

unread,
Apr 8, 2008, 5:20:11 PM4/8/08
to
Hi Davide,

I was doing some playing about with signalfd(), and seem to have encountered a
bug: when a signalfd read() fetches data for a signal that was sent by
sigqueue(), the data accompanying the signal is not returned. Instead
ssi_int/ssi_ptr is zero.

I've not looked into the cause of the problem, but the programs below can be
used to demonstrate it.

Here's an example run:

# Run in the background, waiting for signal 44.
$ ./signalfd_sigval 44 &
./signalfd_sigval: PID = 14783
[1] 14783
# Send signal 44 to PID 14783 with accompanying data 123
$ ./sigqueue 14783 44 123
/home/mtk/alp/signals/sigqueue: PID = 14784
Got signal 44
ssi_code= -1
ssi_pid = 14784
ssi_uid = 1000
ssi_int = 0 <= should be 123 here
ssi_ptr = 0 <= and here the hex version of 123

Could you take a look at this?

Cheers,

Michael


/* signalfd_sigval.c */

#define _GNU_SOURCE
#include <sys/syscall.h>
#include <unistd.h>
#include <stdint.h>
#include <signal.h>
#if defined(__i386__)
#define __NR_signalfd 321
#endif

struct signalfd_siginfo {
uint32_t ssi_signo;
int32_t ssi_errno;
int32_t ssi_code;
uint32_t ssi_pid;
uint32_t ssi_uid;
int32_t ssi_fd;
uint32_t ssi_tid;
uint32_t ssi_band;
uint32_t ssi_overrun;
uint32_t ssi_trapno;
int32_t ssi_status;
int32_t ssi_int;
uint64_t ssi_ptr;
uint64_t ssi_utime;
uint64_t ssi_stime;
uint64_t ssi_addr;
uint8_t __pad[48];
};

static int
signalfd(int ufd, sigset_t const *mask)
{
#define SIZEOF_SIG (_NSIG / 8)
#define SIZEOF_SIGSET (SIZEOF_SIG > sizeof(sigset_t) ? \
sizeof(sigset_t): SIZEOF_SIG)
return syscall(__NR_signalfd, ufd, mask, SIZEOF_SIGSET);
}

// #include <sys/signalfd.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>

#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); } while (0)

int
main(int argc, char *argv[])
{
sigset_t mask;
int sfd;
struct signalfd_siginfo fdsi;
ssize_t s;

if (argc != 2) {
fprintf(stderr, "Usage: %s sig-num\n", argv[0]);
exit(EXIT_FAILURE);
}

printf("%s: PID = %ld\n", argv[0], (long) getpid());

sigemptyset(&mask);
sigaddset(&mask, atoi(argv[1]));

if (sigprocmask(SIG_BLOCK, &mask, NULL) == -1)
errExit("sigprocmask");

sfd = signalfd(-1, &mask);
if (sfd == -1)
errExit("signalfd");

for (;;) {
s = read(sfd, &fdsi, sizeof(struct signalfd_siginfo));
if (s != sizeof(struct signalfd_siginfo))
errExit("read");

printf("Got signal %d\n", fdsi.ssi_signo);
printf(" ssi_code= %d\n", fdsi.ssi_code);
printf(" ssi_pid = %d\n", fdsi.ssi_pid);
printf(" ssi_uid = %d\n", fdsi.ssi_uid);
printf(" ssi_int = %d\n", fdsi.ssi_int);
printf(" ssi_ptr = %llx\n", fdsi.ssi_ptr);
}
}

/* sigqueue.c */

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#define errExit(msg) do { perror(msg); exit(EXIT_FAILURE); \
} while (0)

int
main(int argc, char *argv[])
{
union sigval sv;

if (argc != 4) {
fprintf(stderr, "Usage: %s pid sig-num data\n", argv[0]);
exit(EXIT_FAILURE);
}

printf("%s: PID = %ld\n", argv[0], (long) getpid());

sv.sival_int = atoi(argv[3]);
if (sigqueue(atoi(argv[1]), atoi(argv[2]), sv) == -1)
errExit("sigqueue");

exit(EXIT_SUCCESS);
}

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majo...@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

Davide Libenzi

unread,
Apr 8, 2008, 7:40:06 PM4/8/08
to
On Tue, 8 Apr 2008, Michael Kerrisk wrote:

> Hi Davide,
>
> I was doing some playing about with signalfd(), and seem to have encountered a
> bug: when a signalfd read() fetches data for a signal that was sent by
> sigqueue(), the data accompanying the signal is not returned. Instead
> ssi_int/ssi_ptr is zero.

Are you able to fetch those info with, say, sigtimedwait(2)?

- Davide

Michael Kerrisk

unread,
Apr 9, 2008, 2:40:13 AM4/9/08
to
On Wed, Apr 9, 2008 at 1:37 AM, Davide Libenzi <dav...@xmailserver.org> wrote:
> On Tue, 8 Apr 2008, Michael Kerrisk wrote:
>
> > Hi Davide,
> >
> > I was doing some playing about with signalfd(), and seem to have encountered a
> > bug: when a signalfd read() fetches data for a signal that was sent by
> > sigqueue(), the data accompanying the signal is not returned. Instead
> > ssi_int/ssi_ptr is zero.
>
> Are you able to fetch those info with, say, sigtimedwait(2)?

Yes.


--
Michael Kerrisk
Maintainer of the Linux man-pages project
http://www.kernel.org/doc/man-pages/
Want to report a man-pages bug? Look here:
http://www.kernel.org/doc/man-pages/reporting_bugs.html

Davide Libenzi

unread,
Apr 9, 2008, 3:10:09 AM4/9/08
to
On Wed, 9 Apr 2008, Michael Kerrisk wrote:

> On Wed, Apr 9, 2008 at 1:37 AM, Davide Libenzi <dav...@xmailserver.org> wrote:
> > On Tue, 8 Apr 2008, Michael Kerrisk wrote:
> >
> > > Hi Davide,
> > >
> > > I was doing some playing about with signalfd(), and seem to have encountered a
> > > bug: when a signalfd read() fetches data for a signal that was sent by
> > > sigqueue(), the data accompanying the signal is not returned. Instead
> > > ssi_int/ssi_ptr is zero.
> >
> > Are you able to fetch those info with, say, sigtimedwait(2)?
>
> Yes.

Okie, found it. Tomorrow I'll post a patch. Thank you for reporting.

- Davide

Davide Libenzi

unread,
Apr 9, 2008, 4:00:14 PM4/9/08
to
On Tue, 8 Apr 2008, Michael Kerrisk wrote:

> Hi Davide,
>
> I was doing some playing about with signalfd(), and seem to have encountered a
> bug: when a signalfd read() fetches data for a signal that was sent by
> sigqueue(), the data accompanying the signal is not returned. Instead
> ssi_int/ssi_ptr is zero.

Michael, can you give the patch below a spin? I tested it on my x86_64 box
and seems to be working fine:

Got signal 44
ssi_code= -1

ssi_pid = 6314
ssi_uid = 1000
ssi_int = 123
ssi_ptr = 7b


- Davide


---
fs/signalfd.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)

Index: linux-2.6.mod/fs/signalfd.c
===================================================================
--- linux-2.6.mod.orig/fs/signalfd.c 2008-04-09 11:53:37.000000000 -0700
+++ linux-2.6.mod/fs/signalfd.c 2008-04-09 12:05:46.000000000 -0700
@@ -111,9 +111,14 @@
err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
break;
- default: /* this is just in case for now ... */
+ default:
+ /*
+ * This case catches also the signals queued by sigqueue().
+ */
err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
+ err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
+ err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
break;

Michael Kerrisk

unread,
Apr 10, 2008, 1:10:06 AM4/10/08
to
Hi Davide,

> > I was doing some playing about with signalfd(), and seem to have encountered a
> > bug: when a signalfd read() fetches data for a signal that was sent by
> > sigqueue(), the data accompanying the signal is not returned. Instead
> > ssi_int/ssi_ptr is zero.
>
> Michael, can you give the patch below a spin? I tested it on my x86_64 box
> and seems to be working fine:
>
> Got signal 44
> ssi_code= -1
> ssi_pid = 6314
> ssi_uid = 1000
> ssi_int = 123
> ssi_ptr = 7b

This works for me on x86-32. Thanks Davide!

Cheers,

Michael

> ---
> fs/signalfd.c | 7 ++++++-
> 1 file changed, 6 insertions(+), 1 deletion(-)
>
> Index: linux-2.6.mod/fs/signalfd.c
> ===================================================================
> --- linux-2.6.mod.orig/fs/signalfd.c 2008-04-09 11:53:37.000000000 -0700
> +++ linux-2.6.mod/fs/signalfd.c 2008-04-09 12:05:46.000000000 -0700
> @@ -111,9 +111,14 @@
> err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
> err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
> break;
> - default: /* this is just in case for now ... */
> + default:
> + /*
> + * This case catches also the signals queued by sigqueue().
> + */
> err |= __put_user(kinfo->si_pid, &uinfo->ssi_pid);
> err |= __put_user(kinfo->si_uid, &uinfo->ssi_uid);
> + err |= __put_user((long) kinfo->si_ptr, &uinfo->ssi_ptr);
> + err |= __put_user(kinfo->si_int, &uinfo->ssi_int);
> break;
> }
>
>

--

Michael Kerrisk
Maintainer of the Linux man-pages project: http://www.kernel.org/doc/man-pages/
Want to report a man-pages bug? Look here:
http://www.kernel.org/doc/man-pages/reporting_bugs.html

Michael Kerrisk

unread,
Apr 10, 2008, 6:40:23 AM4/10/08
to
On Thu, Apr 10, 2008 at 7:03 AM, Michael Kerrisk
<mtk.ma...@googlemail.com> wrote:
> Hi Davide,
>
> > > I was doing some playing about with signalfd(), and seem to have encountered a
> > > bug: when a signalfd read() fetches data for a signal that was sent by
> > > sigqueue(), the data accompanying the signal is not returned. Instead
> > > ssi_int/ssi_ptr is zero.
> >
> > Michael, can you give the patch below a spin? I tested it on my x86_64 box
> > and seems to be working fine:
> >
> > Got signal 44
> > ssi_code= -1
> > ssi_pid = 6314
> > ssi_uid = 1000
> > ssi_int = 123
> > ssi_ptr = 7b
>
> This works for me on x86-32. Thanks Davide!

Davide,

Are you going to get this pushed into 2.6.26? I assume we can't get
it into 2.6.25...

Davide Libenzi

unread,
Apr 10, 2008, 1:30:13 PM4/10/08
to
On Thu, 10 Apr 2008, Michael Kerrisk wrote:

> On Thu, Apr 10, 2008 at 7:03 AM, Michael Kerrisk
> <mtk.ma...@googlemail.com> wrote:
> > Hi Davide,
> >
> > > > I was doing some playing about with signalfd(), and seem to have encountered a
> > > > bug: when a signalfd read() fetches data for a signal that was sent by
> > > > sigqueue(), the data accompanying the signal is not returned. Instead
> > > > ssi_int/ssi_ptr is zero.
> > >
> > > Michael, can you give the patch below a spin? I tested it on my x86_64 box
> > > and seems to be working fine:
> > >
> > > Got signal 44
> > > ssi_code= -1
> > > ssi_pid = 6314
> > > ssi_uid = 1000
> > > ssi_int = 123
> > > ssi_ptr = 7b
> >
> > This works for me on x86-32. Thanks Davide!
>
> Davide,
>
> Are you going to get this pushed into 2.6.26? I assume we can't get
> it into 2.6.25...

I'll be sending it Andrew-bound today. I dunno where it'll land mainline.


- Davide

0 new messages