0

I am making a program containing a "Server.c" which waits a client to send it a SIGUSR1 msg 10 times, then dies, and a "client.c" which sends a SIGUSR1 msg to the server.

The problem is that if I try to access the siginfo_t* info, I get a segmentation fault.

Note that this is being tested on a Debian ssh server on which I do not have high permissions. Node that this code works fine on Ubuntu.

Can siginfo_t *info fail due to permission issues? Or is there another issue causing this portability problem. As far as I know libc should be fairly standard throughout any linux distro, possibly unix.

Any Ideas?

Thanks

server.c

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

int counter = 0;
pid_t *clients = 0;

void on_signal(int signo, siginfo_t *info, void * context)
{
    puts("SIGNAL RECEIVED");
    assert(clients);
    clients[counter] = info->si_pid;
    ++counter;
}

int main()
{
    struct sigaction action;
    sigset_t set;
    int recieveflag = 0;

    clients = (pid_t*)malloc(10 * sizeof(pid_t));

    sigemptyset(&set);
    sigaddset(&set, SA_SIGINFO);

    memset(&action, 0, sizeof(struct sigaction));
    action.sa_sigaction = on_signal;
    sigaction(SIGUSR1, &action, 0);

    while (counter < 10) {
        //sigprocmask(SIG_BLOCK, &set, 0);
        sigsuspend(&set);
    }

    puts("I'm done!");

    return 0;
}

client.c:

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

int main(int argc, const char** argv)
{
    int server_id;

    assert(argc == 2);

    server_id = atoi(argv[1]);
    assert(server_id > 0);

    kill(server_id, SIGUSR1);  

    return 0;
}

I tried editing server.c to:

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

int counter = 0;
pid_t *clients = 0;

void on_signal(int sig)
{
    puts("SIGNAL RECEIVED");
}

int main()
{
    struct sigaction action;
    sigset_t set;
    int recieveflag = 0;

    clients = (pid_t*)malloc(10 * sizeof(pid_t));

    sigemptyset(&set);
    sigaddset(&set, SIGUSR1);

    memset(&action, 0, sizeof(struct sigaction));
    action.sa_flags = SA_SIGINFO;
    action.sa_handler = on_signal;
    sigaction(SIGUSR1, &action, 0);

    while (counter < 10) {
        sigprocmask(SIG_BLOCK, &set, 0);
        sigsuspend(&set);
        ++counter;
    }

    puts("I'm done!");

    return 0;
}

now it no longer receives the SIGUSR1 event at all.

Dmytro
  • 5,068
  • 4
  • 39
  • 50

1 Answers1

4

The basic behavior of sigaction is to call a simple callback like : void (*sa_handler)(int);. So if you want to use the sigaction handle with 3 parameters void (*sa_sigaction)(int, siginfo_t *, void *);, you must set the sa_flags field of your struct sigaction with the flag SA_SIGINFO. Take a look of the man page : http://www.kernel.org/doc/man-pages/online/pages/man2/sigaction.2.html who is clear.

Hulor
  • 219
  • 1
  • 5
  • Sorry, I don't see where it's set. If you mean you set it by ` sigaddset(&set, SA_SIGINFO);`, sigaddset just create a list of signal. into the sigset_t. So this don't set any field on your struct sigaction. Also there is a mistake on your sigaddset, you add a define of the bit flag SA_SIGINFO, but this is not a signal... – Hulor Mar 01 '13 at 01:38
  • I figured it out, this appears to be indeed the case. – Dmytro Mar 02 '13 at 07:23
  • @Hulor, I have done this but I still get segmentation fault. Any ideas? If I comment the lines accessing that variable there's no fault, so not sure why that's happening. – Chef Pharaoh Nov 09 '16 at 23:10
  • Finally figured it out. I need to set the flag before registering to the signals I want to handle... phew! – Chef Pharaoh Nov 10 '16 at 00:14