subprocess.Popen inheriting

Gabriel Genellina gagsl-py2 at yahoo.com.ar
Thu Dec 18 20:21:06 EST 2008


En Thu, 18 Dec 2008 19:46:45 -0200, Aaron Brady <castironpi at gmail.com>  
escribió:

> On Dec 17, 7:16 pm, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
> wrote:
>> En Wed, 17 Dec 2008 22:46:32 -0200, Aaron Brady <castiro... at gmail.com>  
>> escribió:
>>
>>
>>
>> > On Dec 17, 5:05 pm, "Gabriel Genellina" <gagsl-... at yahoo.com.ar>
>> > wrote:
>> >> En Wed, 17 Dec 2008 12:21:38 -0200, Jeremy Sanders  
>> >> <jeremy+complangpyt... at jeremysanders.net> escribió:
>>
>> >> > It would be nice if Python created pipes that are properly  
>> >> inheritable by
>> >> > default by child processes, as they're mostly used for IPC.
>>
>> >> I'd say it is a bug in os.pipe implementation; they should be  
>> >> inheritable  
>> >> by default, as in posix (after all, the code is in "posixmodule.c").
>>
>> > The code looks like this:
>>
>> >    ok = CreatePipe(&read, &write, NULL, 0);
>> >    Py_END_ALLOW_THREADS
>> >    if (!ok)
>> >            return win32_error("CreatePipe", NULL);
>> >    read_fd = _open_osfhandle((Py_intptr_t)read, 0);
>> >    write_fd = _open_osfhandle((Py_intptr_t)write, 1);
>>
>> > 'If lpPipeAttributes is NULL, the handle cannot be inherited.'  You
>> > could populate a 'SECURITY_ATTRIBUTES' structure, or call
>> > DuplicateHandle on both of them.
>>
>> > A patch would look like this:
>>
>> > SECURITY_ATTRIBUTES sattribs;
>> > sattribs.nLength = sizeof(sattribs);
>> > sattribs.lpSecurityDescriptor = NULL;
>> > sattribs.bInheritHandle = TRUE;
>> > ok = CreatePipe(&read, &write, &sattribs, 0);
>>
>> Yes, that's exactly how os.popen does it (in posixmodule.c)
>>
>> > This still doesn't answer whether the file descriptor return by
>> > '_open_osfhandle' can be inherited too.
>>
>> It doesn't matter. The OS only cares about file handles, not C RTL  
>> structures.
>
> Sorry for the multiple posts.  File handles are inheritable by child
> processes, if the permissions are right.  File descriptors are not.
> Is there a way that we can get the handles of a pipe into code, so
> that we can pass them to a subprocess?

On Windows, file handles are the real OS stuff, the "true" reference to an  
open file. File descriptors are not, they exist only to please the C  
runtime library. Programs not written in C (directly, or indirectly like  
Python) don't care at all about file descriptors. And in case one actually  
cares, there is _open_osfhandle in the C RTL (available as  
msvcrt.open_osfhandle from Python).
A subprocess may inherit handles from its parent [there are two filters:  
the parameter "bInheritHandles" in the CreateProcess call provides global  
control, and individual handles can be made inheritable or not, before  
creating the new subprocess].
"Anonymous" pipes are good to replace stdin/stdout/stderr, because there  
is no need to explicitely communicate the handle value to the subprocess:  
one just replaces the corresponding handle with the desired pipe, and the  
subprocess might not even notice it.
In case this is not enough, one might pass the handle (as a number) in the  
command line, but probably a "named pipe" would be better. As this is not  
transparent for the child process, one must explicitely code such things.

> Will it take calling
> 'CreatePipe' from ctypes directly if on Windows?  Or can 'os.pipe' be
> made to abstract that?  If Windows can't inherit descriptors,
> 'os.pipe' should return handles, and 'os.read' &co. should accept
> them.

I think the best way would be to modify os.pipe so it returns inheritable  
pipes, as it should have been from the beginning.

> It is a fairly large patch.

Not at all, you have already posted most of it.

-- 
Gabriel Genellina




More information about the Python-list mailing list