2013/1/10 Antoine Pitrou firstname.lastname@example.org:
I changed my mind, the PEP does not propose to change the *default* behaviour (don't set close-on-exec by default).
But the PEP proposes to *add a function* to change the default behaviour. Application developers taking care of security can set close-on-exec by default, but they will have maybe to fix bugs (add cloexec=False argument, call os.set_cloexec(fd, True)) because something may expect an inheried file descriptor.
Do you have an example of what that "something" may be? Apart from standard streams, I can't think of any inherited file descriptor an external program would want to rely on.
In other words, I think close-on-exec by default is probably a reasonable decision.
Network servers like inetd or apache MPM (prefork) uses a process listening on a socket, and then fork to execute a request in a child process. I don't know how it works exactly, but I guess that the child process need a socket from the parent to send the answer to the client. If the socket is closed on execute (ex: Apache with CGI), it does not work :-)
Example with CGIHTTPRequestHandler.run_cgi(), self.connection is the socket coming from accept():
self.rfile = self.connection.makefile('rb', self.rbufsize) self.wfile = self.connection.makefile('wb', self.wbufsize) ... try: os.setuid(nobody) except OSError: pass os.dup2(self.rfile.fileno(), 0) os.dup2(self.wfile.fileno(), 1) os.execve(scriptfile, args, env)
We are talking about *one* specific socket. So if close-on-exec flag is set on all file descriptors, it should be easy to only unset it on one specific file descriptor. For example, the fix for StreamRequestHandler.setup() would be simple, just add cloexec=True to dup2:
os.dup2(self.rfile.fileno(), 0, cloexec=False) os.dup2(self.wfile.fileno(), 1, cloexec=False)
Such servers is not the common case, but more the exception. So setting close-on-exec by default makes sense.
I don't know if there are other use cases using fork()+exec() and *inheriting* one or more file descriptors.
On Windows, the CGI server uses a classic PIPE to get the output of the subprocess and then copy data from the pipe into the socket.