* lib/windows-spawn.h (KEEP_OPEN_IN_PARENT): New macro.
* lib/windows-spawn.c (init_inheritable_handles): When a handle is
already inheritable, don't bother duplicating it; instead, just mark it
as KEEP_OPEN_IN_PARENT.
* lib/spawni.c (shrink_inheritable_handles, close_inheritable_handles,
do_open, do_dup2, do_close): Don't close handles that are marked as
KEEP_OPEN_IN_PARENT.
+2022-09-09 Bruno Haible <bruno@clisp.org>
+
+ posix_spawn-internal: Optimize DuplicateHandle calls on native Windows.
+ * lib/windows-spawn.h (KEEP_OPEN_IN_PARENT): New macro.
+ * lib/windows-spawn.c (init_inheritable_handles): When a handle is
+ already inheritable, don't bother duplicating it; instead, just mark it
+ as KEEP_OPEN_IN_PARENT.
+ * lib/spawni.c (shrink_inheritable_handles, close_inheritable_handles,
+ do_open, do_dup2, do_close): Don't close handles that are marked as
+ KEEP_OPEN_IN_PARENT.
+
2022-09-09 Bruno Haible <bruno@clisp.org>
posix_spawn-internal: Don't lose flags while duplicating an fd.
if (handle != INVALID_HANDLE_VALUE
&& (flags[fd] & KEEP_OPEN_IN_CHILD) == 0)
{
- CloseHandle (handle);
+ if (!(flags[fd] & KEEP_OPEN_IN_PARENT))
+ CloseHandle (handle);
handles[fd] = INVALID_HANDLE_VALUE;
}
}
close_inheritable_handles (struct inheritable_handles *inh_handles)
{
HANDLE *handles = inh_handles->handles;
+ unsigned short *flags = inh_handles->flags;
size_t handles_count = inh_handles->count;
unsigned int fd;
{
HANDLE handle = handles[fd];
- if (handle != INVALID_HANDLE_VALUE)
+ if (handle != INVALID_HANDLE_VALUE
+ && !(flags[fd] & KEEP_OPEN_IN_PARENT))
CloseHandle (handle);
}
}
if (grow_inheritable_handles (inh_handles, newfd) < 0)
return -1;
if (inh_handles->handles[newfd] != INVALID_HANDLE_VALUE
+ && !(inh_handles->flags[newfd] & KEEP_OPEN_IN_PARENT)
&& !CloseHandle (inh_handles->handles[newfd]))
{
errno = EIO;
if (grow_inheritable_handles (inh_handles, newfd) < 0)
return -1;
if (inh_handles->handles[newfd] != INVALID_HANDLE_VALUE
+ && !(inh_handles->flags[newfd] & KEEP_OPEN_IN_PARENT)
&& !CloseHandle (inh_handles->handles[newfd]))
{
errno = EIO;
errno = EBADF;
return -1;
}
- if (!CloseHandle (inh_handles->handles[fd]))
+ if (!(inh_handles->flags[fd] & KEEP_OPEN_IN_PARENT)
+ && !CloseHandle (inh_handles->handles[fd]))
{
errno = EIO;
return -1;
{
/* Add fd to the array, regardless of whether it is
inheritable or not. */
- if (!DuplicateHandle (curr_process, handle,
- curr_process, &handles_array[fd],
- 0, TRUE, DUPLICATE_SAME_ACCESS))
+ if ((hflags & HANDLE_FLAG_INHERIT) != 0)
+ {
+ /* Instead of duplicating it, just mark it as shared. */
+ handles_array[fd] = handle;
+ flags_array[fd] = KEEP_OPEN_IN_PARENT | KEEP_OPEN_IN_CHILD;
+ }
+ else
{
- unsigned int i;
- for (i = 0; i < fd; i++)
- if (handles_array[i] != INVALID_HANDLE_VALUE)
- CloseHandle (handles_array[i]);
- free (flags_array);
- free (handles_array);
- errno = EBADF; /* arbitrary */
- return -1;
+ if (!DuplicateHandle (curr_process, handle,
+ curr_process, &handles_array[fd],
+ 0, TRUE, DUPLICATE_SAME_ACCESS))
+ {
+ unsigned int i;
+ for (i = 0; i < fd; i++)
+ if (handles_array[i] != INVALID_HANDLE_VALUE
+ && !(flags_array[i] & KEEP_OPEN_IN_PARENT))
+ CloseHandle (handles_array[i]);
+ free (flags_array);
+ free (handles_array);
+ errno = EBADF; /* arbitrary */
+ return -1;
+ }
+ flags_array[fd] = 0;
}
- flags_array[fd] =
- ((hflags & HANDLE_FLAG_INHERIT) != 0 ? KEEP_OPEN_IN_CHILD : 0);
}
else
{
- 32 for O_APPEND.
- KEEP_OPEN_IN_CHILD if handles[fd] is scheduled to be preserved in the
child process.
+ - KEEP_OPEN_IN_PARENT if handles[fd] is shared with (and needs to be kept
+ open in) the parent process.
*/
unsigned short *flags;
#define KEEP_OPEN_IN_CHILD 0x100
+ #define KEEP_OPEN_IN_PARENT 0x200
};
/* Initializes a set of inheritable handles, filling in all or part of the