-1

I'm coding a program and I settled up a signal handler for SIGINT:

volatile int exit_program = 0; //Global variable

void exit_client() {
    write(1, "Disconnecting...\n", strlen("Disconnecting...\n"));
    exit_program = 1;
}

Then in main I told the process to react with exit_client() when a SIGINT is received.

int main() {
    signal(SIGINT, exit_client);
    //...
}

Later on in the main process I have the following code:

while (!exit_program) {

    //...

    socket_rcv(server_socket);
}

close(server_socket);
write(1, "Disconnected\n", strlen("Disconnected\n"));
    

I use socket_rcv() to receive data from the server socket and also to send a SIGINT to the process if the read() return value is 0 (when the server disconnects). I do this executing: raise(SIGINT):

socket_data socket_rcv(int socket) {
        
    //...

    do {
        bytes_read = read(socket, sequence + (115 - total_bytes), total_bytes+10);

        if (bytes_read == -1) write(1, "Read error\n", strlen("Read error\n"));
        if (bytes_read == 0) raise(SIGINT);
        total_bytes -= bytes_read;

    } while (total_bytes > 0);

    //...
}

But, when executing both server and client and disconnecting the server first, to see how the client reacts (should print Disconnecting... and then Disconnected as well as the server socket is closed), I only get the print in the signal handler to confirm the signal handler executes but then the program terminates and it doesn't continue it's execution in order to close the socket and execute the last write(1, "Disconnected\n", strlen("Disconnected\n"));.

Why does it terminate and how can I fix this?

Also, might be irrelevant but socket_rcv() function is declared in another .c file, including its .h module where the main process is.

William Pursell
  • 204,365
  • 48
  • 270
  • 300
user157629
  • 624
  • 4
  • 17
  • Why do you need the signal at all? Why not just set `exit_program` directly? – kaylum Jan 09 '21 at 21:36
  • 1
    Can you create a [mcve]? – Nate Eldredge Jan 09 '21 at 21:58
  • Note that in general it is better to use `sigaction` instead of `signal`. – Nate Eldredge Jan 09 '21 at 22:01
  • @kaylum because the program does not end until I press `CTRL + C` which sends a `SIGINT` to that process to then exit the loop and `free()` used memory and close some file descriptors – user157629 Jan 09 '21 at 22:54
  • Not sure how pressing Ctrl+C fits into the picture, you might want to integrate that into the overall story. Be aware that `signal()` is installing a one-shot handler, if you get two sigints, the second one will use the default handler and immediately nuke the process. `raise` will not exit the socket_rcv function so you will probably get the disconnecting print, go back to being stuck inside `socket_rcv` and then press ^C and see above. –  Jan 10 '21 at 00:41
  • I second what @kaylum is saying. You do not need signals to send this kind of message to yourself. Set the variable and return from `socket_rcv`, that's it. You don't have to clown around with signals and `raise`. –  Jan 10 '21 at 00:45

1 Answers1

0

I agree with the commenters, why use a signal handler when you can set exit_program directly?

Anyway, your problem seems to be lying somewhere else (maybe read?) or you're not giving us the full picture because this piece of code works:

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

volatile int exit_program = 0;

void exit_handler(int sig) {
    write(1, "exit_handler\n", strlen("exit_handler\n"));
    exit_program = 1;
}

int main() {
    int i = 0;

    signal(SIGINT, exit_handler);

    while (!exit_program) {
        write(1, "loop\n", strlen("loop\n"));

        if (i == 1) {
            raise(SIGINT);
        }

        ++i;
    }

    write(1, "done\n", strlen("done\n"));

    return 0;
}

Prints

loop
loop
exit_handler
done
Marco
  • 7,007
  • 2
  • 19
  • 49