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

Viewed 432

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?

1 Answers

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);
  }
}
Related