This reminds me of a bug I was hunting years ago in an obscure web server software written in C that was ported from Unix (Solaris perhaps) to Windows. It implemented connections to backend-systems and databases using sockets. Sometimes we got random file errors out of nowhere on Windows but not on Unix.
Turns out BSD sockets are closed with close() just like file descriptors but winsock requires applications to use closesocket(). The guy that ported this to Windows didn't know this and used close() on sockets leaving them dangling and sometimes closing random files on specific circumstances.
Dealing with stdin/stdout/stderr is much harder on Windows than on Unix.
On Unix, you have the stdio layer (FILE *) and the file descriptor layer. On Windows, you have multiple stdio layers (one for each C runtime you have loaded in your process), multiple file descriptor layers (again, one for each C runtime), and the native "standard handles" layer (GetStdHandle/SetStdHandle).
On Unix, to redirect stdout is just a dup2() call, perhaps preceded by a fflush. But on Windows, there's no handle equivalent of dup2() (DuplicateHandle can duplicate a handle, but it will give you a new handle; you cannot use it to replace an existing handle).
So you have to either use SetStdHandle, which won't work well on multithreaded programs (see the comments for the blog post at http://blogs.msdn.com/b/oldnewthing/archive/2013/03/07/10399...), or call a dup2() equivalent on each C runtime the process is using, which won't work if (as in the second bug report in this article) another component is directly using the underlying handle.
On windows you use DuplicateHandle() on pipes made by CreatePipe(). You can then pass these handles to, for example, CreateProcess() (which does what the name implies). Now when the child process writes to a handle (stdout), the parent process can then read from this handle as if it were stdin.
These problems would basically all go away if you used a process monitor to handle setting up the environment for the server process, including fds 1 and 2, and then just let it log to stdout or stderr. Any halfway-decent process monitor can do this, and most of them can handle log rotation as well.
9 comments
[ 3.9 ms ] story [ 29.2 ms ] threadTurns out BSD sockets are closed with close() just like file descriptors but winsock requires applications to use closesocket(). The guy that ported this to Windows didn't know this and used close() on sockets leaving them dangling and sometimes closing random files on specific circumstances.
On Unix, you have the stdio layer (FILE *) and the file descriptor layer. On Windows, you have multiple stdio layers (one for each C runtime you have loaded in your process), multiple file descriptor layers (again, one for each C runtime), and the native "standard handles" layer (GetStdHandle/SetStdHandle).
On Unix, to redirect stdout is just a dup2() call, perhaps preceded by a fflush. But on Windows, there's no handle equivalent of dup2() (DuplicateHandle can duplicate a handle, but it will give you a new handle; you cannot use it to replace an existing handle).
So you have to either use SetStdHandle, which won't work well on multithreaded programs (see the comments for the blog post at http://blogs.msdn.com/b/oldnewthing/archive/2013/03/07/10399...), or call a dup2() equivalent on each C runtime the process is using, which won't work if (as in the second bug report in this article) another component is directly using the underlying handle.