0

just this short question: how do we close the FIFO file if we receive the SIGTERM and exit. If my file is a normal file, it works. But if it is a FIFO, it doesn't work. Any ideas? Thanks :)

/**
    with the help of these guys, 
    it is not a good approach to write it, 
    though it works. close(fd) is pointless here.
**/

    FILE * myfile;
    int fd;
    void sig_handler(int signum) {
        if (signum == SIGTERM) {
            *close(fd);*
            fclose(myfile);
            printf("caught SIGTERM\n");
            exit(EXIT_SUCCESS);
        }
    }
    int main(void) {
        myfile = fopen("file", "w+");
        fd = open("myfifo", O_RDONLY);
        {
            struct sigaction act;
            memset(&act, 0, sizeof(act));
            act.sa_handler = sig_handler;
            sigaction(SIGTERM, &act, 0);
        }
        for(;;)
            pause();
        return 0;
    }
4af2e9eb6
  • 682
  • 3
  • 7
  • 20

1 Answers1

1

You have to set the signal handler before opening the FIFO. My Unix FIFO's are a little rusty :) but I suspect that the open is blocking for the peer to open it also. So when you kill the process, it is not actually waiting inside your loop, but inside the open and so the signal handler does not go off.

On a different note, fclose in a signal handler is a bad idea. What if an I/O library operation is interrupted by the signal? The library is not reentrant from signal handlers. Only certain "async safe" functions can be used from signal handlers. Antoher one is exit, which does complicated things inside the library, many of which are not safe from an asynchronous signal handler. The _exit function should be used instead.

Worrying whether memory leaked, if you're causing the process to exit from a signal handler, is pointless, and impossible to get "right". For one thing, malloc itself might be interrupted by the signal handler; it is not safe to call free to liberate anything.

Kaz
  • 55,781
  • 9
  • 100
  • 149
  • Just tested it: `open(path, O_RDONLY)` on a FIFO that isn't opened for writing blocks. – thejh Jun 10 '13 at 01:57
  • I moved the fd=open(...) in between the local block and for loop, it doesn't make any difference :( – 4af2e9eb6 Jun 10 '13 at 01:59
  • @thejh Yeah, this program just receive from that pipe. – 4af2e9eb6 Jun 10 '13 at 02:00
  • Thanks a lot, Kaz! There are a lot of information in your answer. – 4af2e9eb6 Jun 10 '13 at 02:07
  • So, now my understanding is: if I don't fclose the file here, where else should I do it? Actually that file in my program is a log file, so it will log the last information "program closed" when SIGTERM being caught and then close the file. If I don't do it over here, there will be one more leak. – 4af2e9eb6 Jun 10 '13 at 02:12
  • @KittenTom Ah, now we are peeling the layers of the onion to get to the real problem. You want the last bit of logging sent to the `FILE *` stream before the signal was received, ha. – Kaz Jun 10 '13 at 02:16
  • If it's a signal that can be handled and ignored, what you can do is just set some global flag which indicates "termination has been requested". Then the main program can clean up and exit gracefully at the first opportunity. If you want the last bit of logging close to an event such as a crash or the delivery of a fatal signal that cannot even be caught, then you have consider using a stream in line buffered mode which flushes every time a newline character is printed. (Or even an unbuffered one, but line buffering is a compromise between being up to date, and efficiency). – Kaz Jun 10 '13 at 02:19
  • @Kaz Thanks you very much for all the advices. The problem is caused by closing the file. It is cause by something else. ;) – 4af2e9eb6 Jun 10 '13 at 02:22