Search code examples
cwindowspipepopen

How can I handle _popen() errors in C?


Good morning; Right now, I'm writing a program which makes a Montecarlo simulation of a physical process and then pipes the data generated to gnuplot to plot a graphical representation. The simulation and plotting work just fine; but I'm interested in printing an error message which informs the user that gnuplot is not installed. In order to manage this, I've tried the following code:

#include <stdio.h>
#include <stdlib.h>
FILE *pipe_gnuplot;
int main() 
{
    pipe_gnuplot = _popen("gnuplot -persist", "w");
    if (pipe_gnuplot==NULL)
    {
        printf("ERROR. INSTALL gnuplot FIRST!\n");
        exit (1);
    }
    return 0;
}

But, instead of printing my error message, "gnuplot is not recognized as an internal or external command, operable program or batch file" appears (the program runs on Windows). I don't understand what I'm doing wrong. According to _popen documentation, NULL should be returned if the pipe opening fails. Can you help me managing this issue? Thanks in advance and sorry if the question is very basic.


Solution

  • Error handling of popen (or _popen) is difficult.

    popen creates a pipe and a process. If this fails, you will get a NULL result, but this occurs only in rare cases. (no more system resources to create a pipe or process or wrong second argument)

    popen passes your command line to a shell (UNIX) or to the command processor (Windows). I'm not sure if you would get a NULL result if the system cannot execute the shell or command processor respectively.

    The command line will be parsed by the shell or command processor and errors are handled as if you entered the command manually, e.g. resulting in an error message and/or a non-zero exit code.

    A successful popen means nothing more than that the system could successfully start the shell or command processor. There is no direct way to check for errors executing the command or to get the exit code of the command.

    Generally I would avoid using popen if possible.

    If you want to program specifically for Windows, check if you can get better error handling from Windows API functions like CreateProcess.

    Otherwise you could wrap your command in a script that checks the result and prints specific messages you can read and parse to distinguish between success and error. (I don't recommend this approach.)