Date: Tue, 3 Jun 1997 16:57:46 +0300 (IDT) From: Eli Zaretskii To: djgpp-workers AT delorie DOT com cc: Daisuke Aoyama Subject: Passing file handles to child programs Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk Here's a problem of which I'm aware for a long time, but only now have I seen a real-world example where it causes trouble. DJGPP calls DOS OpenFile function (Int 21h/AH=3Dh) in a way that makes the resulting handle be inherited by the child programs. However, DOS has a misfeature whereby the child only inherits the first 20 handles (which get copied into its default handle table in the PSP). Here's how this bug can bite you: 1) When a parent DJGPP program has used up its 20-handle table, it calls a DOS function that enlarges handles and bravely moves on. 2) The DOS function in point allocates a new handle table, copies the 20 handles into it and updates the pointer in the PSP to point to the new table. 3) When you call a child program, DOS copies the first 20 handles into the PSP of the child and invokes the child. 4) The child starts without even a single free handle to begin with. A DJGPP-specific aspect of this problem is that the child program won't start because the stub cannot open the .exe file to read the COFF header. That is how I bumped into this problem (it was a Dvilj4 job that needed a lot of fonts, and it was calling external programs to generate the missing fonts). Solutions? I can think of two: a) Change low-level libc functions so that they open files with a non-inherit bit. It is a rare program that really needs this on MS-DOS, most of the handles beyond the first 5 don't need to be inherited (in fact, first thing that COMMAND.COM does when it starts is to close all handles from 6 on). If we NEVER need the inheritance, this is the best solution. However, I'm afraid that Bash relies on the inheritance sometimes (to support constructs like "6> foo"), and other programs might need this too. Can anybody comment on this? b) The second way is a bit kludgy but safer, I think. We can reserve a couple of handles in the first 20 and close them in the code that invokes child programs, so that at least a few handles are free on the child side. When the child returns, we just reopen them (say, on NUL device). Comments?