简体   繁体   中英

sigpipe c server/client - where does the program restart?

I've a client/server program, now I want to handle signals. When the client closes the connection (if for example I close the terminal), the server has to handle a SIGPIPE, am I right? I'd like to implement something like this. Is it possible?

server.c:

void function(){
   printf("...");
   read(socket,buff,size);
   //IF THE CLIENT CLOSES, THE SERVER RECEIVES A SIGPIPE
   ...the resting part of the scheduled code should be ignored if sigpipe is received, and the program should begin from where I wrote on the handler of the sigpipe...
   printf("not working"); //this should be ignored, but it's printed 2 times immediatly, and when I've finished the actions indicated in the function by the handler, it prints it another time, because the program counter restarts from here...
}

void sigpipehandler(){
   close(socket);
   main(); //I'd like that the program restarts from the main when I've received a SIGPIPE. It restarts from the main, but only after having printed "not working" two times...
}

int main(){
   sigPipe.sa_sigaction = &sigpipehandler;
   sigPipe.sa_flags = SA_SIGINFO;
   sigaction(SIGPIPE, &sigpipehandler, NULL);
   ...code...
}

Converting comments into an answer.

Note that you only get SIGPIPE when you write to a pipe where there is no process with the read end of the pipe open. You get EOF (zero bytes read) when you read from a pipe that has no process with the write end of the pipe open.

So, if I change the read() with a write() in the example. How can I handle the SIGPIPE?

Simplest is to ignore SIGPIPE ( signal(SIGPIPE, SIG_IGN) ) and then monitor the return value from write() . If it comes back with -1 and errno set to EINTR , you can assume you got interrupted by some signal, and most probably a SIGPIPE, especially if you don't have any other signal handling set. Of course, you should be looking at the return value from write() — and read() — anyway.

Alternatively, if you want an explicit SIGPIPE handler, then you definitely do not want to recursively call main() from your signal handler. You can write a loop in main() , and have the signal handler set a flag which you test in the loop. Per Standard C, about the only thing you can do in a signal handler is modify a variable or exit.

static volatile sigatomic_t sig_recvd = 0;
static int sock_fd = -1;

void sigpipehandler(int signum)
{
   close(sock_fd);
   sock_fd = -1;
   sig_recvd = signum;
}

int main(void)
{
    sigPipe.sa_sigaction = &sigpipehandler;
    sigPipe.sa_flags = SA_SIGINFO;
    sigemptyset(&sigPipe.sa_mask);
    sigaction(SIGPIPE, &sigpipehandler, NULL);

    int done = 0;

    while (!done)
    {
        if (sock_fd == -1)
        {
            if (sig_recvd != 0)
            {
                ...report signal received...
                sig_recvd = 0;
            }
            ...(re)open socket on sock_fd...
        }
        ...code as before - sets done = 1 when loop should terminate...
    }
    return 0;
}

Note that naming a variable the same as a system call ( socket in your code) is treading on thin ice; hence, I renamed it sock_fd . A global variable called socket would be a really bad idea.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM