7

Some months ago I write a CGI application for Linux that uses popen() to read the output of a command, and then I close the pipe with fclose().

Now, I read that for close pipes is needs use pclose().

The manual says:

The return value from popen() is a normal standard I/O stream in all respects save that it must be closed with pclose() rather than fclose(3).

My code is like this:

if ((NULL != (f = popen(command.value, "r")))) {
    //do something
    fclose(f);
}

My question is:

My mistake have a security concern? It program is currently in production. In tests it not do anything problem. Is really needed, patch it using pclose() instead fclose() ? Note: I only open the PIPE one time in the program.

Today, in my local home I do some test and fclose() and pclose() not return EOF indicating failure.

Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
carlos
  • 1,261
  • 1
  • 12
  • 15
  • 2
    You have Undefined behavior: Read [`pclose()` vs `fclose()`?](http://cboard.cprogramming.com/cplusplus-programming/97147-pclose-vs-fclose.html) : The `_pclose` function looks up the process ID of the command processor (CMD.EXE) started by the associated `_popen` call, executes a `_cwait` call on the new command processor, and closes the stream on the associated pipe.` – Grijesh Chauhan Aug 19 '13 at 16:16
  • There are some SO posts related to your question: 1. [`fclose()/pclose()` may block on some file pointers](http://stackoverflow.com/questions/1736983/fclose-pclose-may-block-on-some-file-pointers) and [How close pipe handle in unix? `(fclose() of pclose())`?](http://stackoverflow.com/questions/5548364/how-close-pipe-handle-in-unix-fclose-of-pclose) – Grijesh Chauhan Aug 19 '13 at 16:19
  • thanks, I will fix because is really important. Now, i look the impact. – carlos Aug 19 '13 at 17:06
  • On Linux, the `libc` implementing `popen` is often free software. So just study the source code of your libc. I guess that not callling `popen` means that `waitpid` won't be called, and you'll have zombie processes. But I leave you to check. – Basile Starynkevitch Oct 27 '17 at 19:18

3 Answers3

11

According to this thread, using fclose instead of pclose means that the process at the other end of the pipe doesn't get reaped, so it stays zombied.

C. K. Young
  • 219,335
  • 46
  • 382
  • 435
6

If you use fclose on the pipe, you will have file descriptor leaks, since fclose will not free the file pointer in the kernel (which is created when you create the pipe since its a file).

While your testing so far hasn't shown any problems, run your program 3000 times (or how ever many file descriptors are allowed, upwards of an int I think) and watch when you will n o longer be able to create pipes.

KrisSodroski
  • 2,796
  • 3
  • 24
  • 39
  • 2
    Typically `fclose` on the stdio stream actually *does* close the underlying pipe descriptor (it's stashed in `fp->_fileno` or whatever the field is named), so it's more a zombie-proc-leak than an fd leak. – torek Aug 19 '13 at 17:40
0

I just found out (after 10 years) that I was mistakingly using fclose for some popen calls, running on windows 2008 server. It worked (i.e. did not crash), and I didn't care about the return code on those calls anyway.

But I needed the return code of the last popen stream, and close was done properly with pclose.

It has the strange effect of returning a 0 error code (maybe collecting the return code of previously not pclosed process), even if the command failed, creating a very strange bug in the code, which could have led to catastrophic errors because the caller thinks that the command worked.

So it's not only a matter of leaking descriptors, it can introduce functional bugs in your code, (even if the application runs for a few seconds and you don't care about leaking descriptors)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • BTW, it is very operating system specific. The OP explicitly asked about Linux. And usual Linux distributions have free software libc, so the OP should study the source code of his particular libc implementation. – Basile Starynkevitch Oct 27 '17 at 19:29
  • ok, but what happened for me on windows could happen on other systems too. – Jean-François Fabre Oct 27 '17 at 19:42
  • Except that the free software aspect is changing a lot how to solve that issue. If your libc (and kernel) was free software, you could inspect and study its source code (and understand what happens). – Basile Starynkevitch Oct 27 '17 at 19:43
  • yes. But even with the source code, that's clearly an error and it's easy to fix so let's not leave it like this. – Jean-François Fabre Oct 27 '17 at 19:45