3

I have the following code in C code in CentOS linux. This code is called every 5 seconds in a thread. The code works fine if I disable pclose(fp), but I know I am supposed to do it. Can someone explain why it hangs at pclose(fp) when I enable it? Many thanks.

FILE* fp;
int status;
char path[255];

fp = popen("ping -c 3 -W 3 200.0.0.51", "r");
sleep(3); 
int i=0; 
while (i < 255) {
    path[i] = fgetc(fp); 
    i++;
}

char* str;
str = strstr(path, "100% packet loss");

if (str!=NULL) {
    //pclose(fp); // <--- hangs here if I enable
    OS_Reboot(); 
}
lppier
  • 1,927
  • 3
  • 24
  • 62

3 Answers3

2

The problem seems to be that pclose() only returns when the process created from popen is terminated, but ping keeps looping forever.

In any case, pclose() shall not return before the child process created by popen() has terminated

A solution would be to fork the process yourself and create pipes for the stdin and stdout that are returned to your process. A possible implementation of this shown here by another stackoverflow member.

Community
  • 1
  • 1
Maurice
  • 610
  • 5
  • 9
  • 1
    Yeah it should, but it seems that it isn't somehow. – Maurice Mar 19 '15 at 02:22
  • 1
    Thanks. I changed it to ping -c 1 -W 1 195.0.0.1 and it works now. Probably the ping processing on the popen didn't terminate quickly enough? – lppier Mar 19 '15 at 02:39
  • Yeah maybe it just took longer then expected to terminate. – Maurice Mar 19 '15 at 02:40
  • One more question: Is the popen process affected by my sleep(3) statement? Or that simply sleeps the thread I am running this function in? – lppier Mar 19 '15 at 02:42
  • 1
    If I recall correctly the fopen creates a new process like fork, so it should not be affected by sleep. – Maurice Mar 19 '15 at 02:46
2

The posted code works fine for me with pclose enabled (I also removed the branch to ensure it would be called). Note that "The pclose() function waits for the associated process to terminate and returns the exit status of the command as returned by wait4(2)" (from the docs) so it could be that "ping -c 3 -W 3 200.0.0.51" is actually hanging on your machine (not sure why it would though).

Matt
  • 724
  • 4
  • 11
2

The behaviour you see should only happen if ping does not terminate, which it should in your case after sending three packets because of the -c 3.

You should maybe add -n to the invocation to avoid getting stuck on DNS lookups in case your connectivity goes down?

Volker Stolz
  • 7,274
  • 1
  • 32
  • 50