Search code examples
cbashposixsystemcat

Can't execute "cat" using system() function in C


I have a function that is the handler of the SIGINT signal in my C program, that when is executed should simply execute the following commands:

void sigint_handler(int sig)
  {
    system("cat output.txt");
    exit(0);
  }

The problem is that the "cat" command doesn't seems to do anything. If I try to do something else instead of "cat", like "echo something" it works fine, so I believe the problem is with the "cat" and not with the system() function. The file "output.txt" is in the same directory of the C program, and if I try to execute cat on that file through another C script it works. Also if I try to execute that command from shell it works.

I've checked the return from the system("cat output.txt") and it's 0. So what can the problem be?

EDIT: The file output.txt is also open as a FILE stream (using fopen()) in the program, by another thread, could that be an issue maybe?


Solution

  • You should know that signal handlers can only safely call a restricted set of async-signal-safe functions. Neither system() nor exit() are on the list. Calling them is likely to trigger undefined behavior, which can lead to unpredictable results.

    You say:

    I see, but I don't understand why his version is working while mine is not. I declare the signal handler in the same way, but my program can't execute that "cat" command, while in his version it does.

    I second Charles Duffy's reply:

    Sometimes things that aren't guaranteed still work despite not being guaranteed as an accident of environment or configuration. That doesn't make the code that just happens to work correct; good code relies only on documented, guaranteed semantics.

    A common workaround for this is to move your signal handling code to the main program, and have the main program periodically check a global variable. From the signal handler all would do is set the global variable and return. This technique will let you do whatever you like, albeit in a somewhat convoluted way.

    volatile sig_atomic_t sigint_received = 0;
    
    void sigint_handler(int sig)
    {  
      sigint_received = 1;
    }
    
    // main program loop
    for (;;) {
      // do stuff
      ...
    
      // check for interruption
      if (sigint_received) {
        system("cat output.txt");
        ​exit(0);
      }
    }