2002-08-27 12:10:54 +08:00
|
|
|
/* child_info.h: shared child info for cygwin
|
2000-09-02 04:54:22 +08:00
|
|
|
|
|
|
|
This file is part of Cygwin.
|
|
|
|
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
|
|
details. */
|
|
|
|
|
2000-09-08 10:56:55 +08:00
|
|
|
#include <setjmp.h>
|
|
|
|
|
2004-12-06 03:41:26 +08:00
|
|
|
enum child_info_types
|
2000-09-02 04:54:22 +08:00
|
|
|
{
|
2011-11-14 09:29:49 +08:00
|
|
|
_CH_NADA = 0,
|
|
|
|
_CH_EXEC = 1,
|
|
|
|
_CH_SPAWN = 2,
|
|
|
|
_CH_FORK = 3,
|
|
|
|
_CH_WHOOPS = 4
|
2000-09-02 04:54:22 +08:00
|
|
|
};
|
|
|
|
|
2006-03-21 02:01:17 +08:00
|
|
|
enum child_status
|
|
|
|
{
|
2006-05-22 12:50:54 +08:00
|
|
|
_CI_STRACED = 0x01,
|
|
|
|
_CI_ISCYGWIN = 0x02,
|
forkables: On fork failure, retry with hardlinks.
To support in-cygwin package managers, the fork() implementation must
not rely on .exe and .dll files to stay in their original location, as
the package manager's job is to replace these files. Instead, when the
first fork try fails, and we have NTFS, we use hardlinks to the original
binaries in /var/run/cygfork/ to create the child process during the
second fork try, along the main.exe.local file to enable the "DotLocal
Dll Redirection" feature for the dlls.
The (probably few) users that need an update-safe fork manually have to
create the /var/run/cygfork/ directory for now, using:
mkdir --mode=a=rwxt /var/run/cygfork
* child_info.h: Bump CURR_CHILD_INFO_MAGIC.
(enum child_status): Add _CI_SILENTFAIL flag.
(struct child_info): Add silentfail setter and getter.
* winsup.h (child_copy): Add bool silentfail parameter.
* cygheap.cc: Pass silentfail parameter to child_copy.
* dcrt0.cc: Ditto.
* dll_init.h (struct dll): Define public inline method forkedntname.
(struct dll_list): Declare private method find_by_forkedntname.
* dll_init.cc (struct dll_list): Implement find_by_forkedntname.
(dll_list::alloc): Use find_by_forkedntname when in load after fork.
(dll_list::load_after_fork_impl): Load dlls using dll::forkedntname.
* fork.cc (frok::parent): Set silentfail child info flag. Pass
silentfail parameter to child_copy. Use forkedntname of
dlls.main_executable.
(fork): When first dofork run failed and did not use forkables,
run dofork again with_forkables set to true.
(child_copy): Use debug_printf if silentfail is true,
system_printf otherwise.
2016-12-07 18:58:28 +08:00
|
|
|
_CI_SAW_CTRL_C = 0x04,
|
|
|
|
_CI_SILENTFAIL = 0x08
|
2006-03-21 02:01:17 +08:00
|
|
|
};
|
|
|
|
|
2001-12-26 12:53:34 +08:00
|
|
|
#define OPROC_MAGIC_MASK 0xff00ff00
|
|
|
|
#define OPROC_MAGIC_GENERIC 0xaf00f000
|
2000-09-02 04:54:22 +08:00
|
|
|
|
2013-08-23 22:32:28 +08:00
|
|
|
#ifdef __x86_64__
|
|
|
|
#define PROC_MAGIC_GENERIC 0xaf00fa64
|
|
|
|
#else /*!x86_64*/
|
|
|
|
#define PROC_MAGIC_GENERIC 0xaf00fa32
|
|
|
|
#endif
|
2001-12-26 12:53:34 +08:00
|
|
|
|
2000-09-02 04:54:22 +08:00
|
|
|
#define EXEC_MAGIC_SIZE sizeof(child_info)
|
2001-12-26 12:53:34 +08:00
|
|
|
|
2006-03-21 02:01:17 +08:00
|
|
|
/* Change this value if you get a message indicating that it is out-of-sync. */
|
2019-02-09 00:48:34 +08:00
|
|
|
#define CURR_CHILD_INFO_MAGIC 0xf4531879U
|
2001-12-26 12:53:34 +08:00
|
|
|
|
2011-10-23 00:26:30 +08:00
|
|
|
#define NPROCS 256
|
|
|
|
|
2011-11-14 09:29:49 +08:00
|
|
|
#include "pinfo.h"
|
2011-10-27 03:42:39 +08:00
|
|
|
struct cchildren
|
|
|
|
{
|
|
|
|
pid_t pid;
|
2011-11-14 09:29:49 +08:00
|
|
|
pinfo_minimal p;
|
2011-10-27 03:42:39 +08:00
|
|
|
};
|
|
|
|
|
2001-12-26 14:18:41 +08:00
|
|
|
/* NOTE: Do not make gratuitous changes to the names or organization of the
|
|
|
|
below class. The layout is checksummed to determine compatibility between
|
|
|
|
different cygwin versions. */
|
2000-09-02 04:54:22 +08:00
|
|
|
class child_info
|
|
|
|
{
|
|
|
|
public:
|
2016-06-25 16:21:13 +08:00
|
|
|
DWORD msv_count; // set to pseudo-count on Vista WOW64, zeroed otherwise
|
2000-09-02 04:54:22 +08:00
|
|
|
DWORD cb; // size of this record
|
2001-12-26 12:53:34 +08:00
|
|
|
DWORD intro; // improbable string
|
2013-04-23 17:44:36 +08:00
|
|
|
DWORD magic; // magic number unique to child_info
|
2001-12-26 12:53:34 +08:00
|
|
|
unsigned short type; // type of record, exec, spawn, fork
|
2011-11-24 05:58:43 +08:00
|
|
|
init_cygheap *cygheap;
|
|
|
|
void *cygheap_max;
|
|
|
|
unsigned char flag;
|
|
|
|
int retry; // number of times we've tried to start child process
|
2012-03-20 23:07:30 +08:00
|
|
|
HANDLE rd_proc_pipe;
|
|
|
|
HANDLE wr_proc_pipe;
|
2000-09-02 04:54:22 +08:00
|
|
|
HANDLE subproc_ready; // used for synchronization with parent
|
2003-09-25 10:29:05 +08:00
|
|
|
HANDLE user_h;
|
2000-10-13 06:15:47 +08:00
|
|
|
HANDLE parent;
|
2012-05-15 06:42:56 +08:00
|
|
|
DWORD parent_winpid;
|
2004-04-04 12:14:11 +08:00
|
|
|
DWORD cygheap_reserve_sz;
|
2001-12-27 05:35:16 +08:00
|
|
|
unsigned fhandler_union_cb;
|
2006-03-19 03:17:21 +08:00
|
|
|
DWORD exit_code; // process exit code
|
|
|
|
static int retry_count;// retry count;
|
2005-07-17 08:51:03 +08:00
|
|
|
child_info (unsigned, child_info_types, bool);
|
2005-08-12 00:13:30 +08:00
|
|
|
child_info (): subproc_ready (NULL), parent (NULL) {}
|
2004-12-06 03:41:26 +08:00
|
|
|
~child_info ();
|
2011-05-30 14:52:12 +08:00
|
|
|
void refresh_cygheap () { cygheap_max = ::cygheap_max; }
|
2004-12-06 03:41:26 +08:00
|
|
|
void ready (bool);
|
2013-01-21 12:34:52 +08:00
|
|
|
bool __reg3 sync (int, HANDLE&, DWORD);
|
|
|
|
DWORD __reg2 proc_retry (HANDLE);
|
2006-03-22 11:20:28 +08:00
|
|
|
bool isstraced () const {return !!(flag & _CI_STRACED);}
|
|
|
|
bool iscygwin () const {return !!(flag & _CI_ISCYGWIN);}
|
2006-05-28 23:50:14 +08:00
|
|
|
bool saw_ctrl_c () const {return !!(flag & _CI_SAW_CTRL_C);}
|
forkables: On fork failure, retry with hardlinks.
To support in-cygwin package managers, the fork() implementation must
not rely on .exe and .dll files to stay in their original location, as
the package manager's job is to replace these files. Instead, when the
first fork try fails, and we have NTFS, we use hardlinks to the original
binaries in /var/run/cygfork/ to create the child process during the
second fork try, along the main.exe.local file to enable the "DotLocal
Dll Redirection" feature for the dlls.
The (probably few) users that need an update-safe fork manually have to
create the /var/run/cygfork/ directory for now, using:
mkdir --mode=a=rwxt /var/run/cygfork
* child_info.h: Bump CURR_CHILD_INFO_MAGIC.
(enum child_status): Add _CI_SILENTFAIL flag.
(struct child_info): Add silentfail setter and getter.
* winsup.h (child_copy): Add bool silentfail parameter.
* cygheap.cc: Pass silentfail parameter to child_copy.
* dcrt0.cc: Ditto.
* dll_init.h (struct dll): Define public inline method forkedntname.
(struct dll_list): Declare private method find_by_forkedntname.
* dll_init.cc (struct dll_list): Implement find_by_forkedntname.
(dll_list::alloc): Use find_by_forkedntname when in load after fork.
(dll_list::load_after_fork_impl): Load dlls using dll::forkedntname.
* fork.cc (frok::parent): Set silentfail child info flag. Pass
silentfail parameter to child_copy. Use forkedntname of
dlls.main_executable.
(fork): When first dofork run failed and did not use forkables,
run dofork again with_forkables set to true.
(child_copy): Use debug_printf if silentfail is true,
system_printf otherwise.
2016-12-07 18:58:28 +08:00
|
|
|
bool silentfail () const {return !!(flag & _CI_SILENTFAIL);}
|
2012-03-20 23:07:30 +08:00
|
|
|
void prefork (bool = false);
|
|
|
|
void cleanup ();
|
2012-03-21 23:54:50 +08:00
|
|
|
void postfork (pinfo& child)
|
|
|
|
{
|
|
|
|
ForceCloseHandle (wr_proc_pipe);
|
|
|
|
wr_proc_pipe = NULL;
|
|
|
|
child.set_rd_proc_pipe (rd_proc_pipe);
|
|
|
|
rd_proc_pipe = NULL;
|
|
|
|
}
|
forkables: On fork failure, retry with hardlinks.
To support in-cygwin package managers, the fork() implementation must
not rely on .exe and .dll files to stay in their original location, as
the package manager's job is to replace these files. Instead, when the
first fork try fails, and we have NTFS, we use hardlinks to the original
binaries in /var/run/cygfork/ to create the child process during the
second fork try, along the main.exe.local file to enable the "DotLocal
Dll Redirection" feature for the dlls.
The (probably few) users that need an update-safe fork manually have to
create the /var/run/cygfork/ directory for now, using:
mkdir --mode=a=rwxt /var/run/cygfork
* child_info.h: Bump CURR_CHILD_INFO_MAGIC.
(enum child_status): Add _CI_SILENTFAIL flag.
(struct child_info): Add silentfail setter and getter.
* winsup.h (child_copy): Add bool silentfail parameter.
* cygheap.cc: Pass silentfail parameter to child_copy.
* dcrt0.cc: Ditto.
* dll_init.h (struct dll): Define public inline method forkedntname.
(struct dll_list): Declare private method find_by_forkedntname.
* dll_init.cc (struct dll_list): Implement find_by_forkedntname.
(dll_list::alloc): Use find_by_forkedntname when in load after fork.
(dll_list::load_after_fork_impl): Load dlls using dll::forkedntname.
* fork.cc (frok::parent): Set silentfail child info flag. Pass
silentfail parameter to child_copy. Use forkedntname of
dlls.main_executable.
(fork): When first dofork run failed and did not use forkables,
run dofork again with_forkables set to true.
(child_copy): Use debug_printf if silentfail is true,
system_printf otherwise.
2016-12-07 18:58:28 +08:00
|
|
|
void silentfail (bool f)
|
|
|
|
{
|
|
|
|
if (f)
|
|
|
|
flag |= _CI_SILENTFAIL;
|
|
|
|
else
|
|
|
|
flag &= ~_CI_SILENTFAIL;
|
|
|
|
}
|
2000-09-02 04:54:22 +08:00
|
|
|
};
|
|
|
|
|
2002-10-15 04:25:52 +08:00
|
|
|
class mount_info;
|
|
|
|
|
2000-09-02 04:54:22 +08:00
|
|
|
class child_info_fork: public child_info
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
HANDLE forker_finished;// for synchronization with child
|
|
|
|
jmp_buf jmp; // where child will jump to
|
2015-12-02 19:31:40 +08:00
|
|
|
void *stackaddr; // DeallocationStack or user-provided allocation address
|
|
|
|
// of parent thread
|
|
|
|
void *stacklimit; // StackLimit of parent thread
|
|
|
|
void *stackbase; // StackBase of parent thread
|
2011-05-20 15:23:11 +08:00
|
|
|
size_t guardsize; // size of POSIX guard region or (size_t) -1 if
|
|
|
|
// user stack
|
2006-12-12 02:55:29 +08:00
|
|
|
char filler[4];
|
2004-12-06 03:41:26 +08:00
|
|
|
child_info_fork ();
|
2013-02-09 04:15:05 +08:00
|
|
|
void __reg1 handle_fork ();
|
2011-05-29 02:17:09 +08:00
|
|
|
bool abort (const char *fmt = NULL, ...);
|
2006-04-04 01:33:07 +08:00
|
|
|
void alloc_stack ();
|
2000-09-02 04:54:22 +08:00
|
|
|
};
|
|
|
|
|
2000-09-03 12:16:35 +08:00
|
|
|
class fhandler_base;
|
|
|
|
|
|
|
|
class cygheap_exec_info
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
int argc;
|
|
|
|
char **argv;
|
2000-10-17 07:55:58 +08:00
|
|
|
int envc;
|
|
|
|
char **envp;
|
2000-09-03 12:16:35 +08:00
|
|
|
HANDLE myself_pinfo;
|
2013-03-31 20:35:44 +08:00
|
|
|
sigset_t sigmask;
|
2011-11-16 12:09:33 +08:00
|
|
|
int nchildren;
|
|
|
|
cchildren children[0];
|
|
|
|
static cygheap_exec_info *alloc ();
|
|
|
|
void record_children ();
|
|
|
|
void reattach_children (HANDLE);
|
2000-09-03 12:16:35 +08:00
|
|
|
};
|
|
|
|
|
|
|
|
class child_info_spawn: public child_info
|
|
|
|
{
|
2011-11-14 09:29:49 +08:00
|
|
|
HANDLE hExeced;
|
|
|
|
HANDLE ev;
|
2019-02-08 22:49:47 +08:00
|
|
|
pid_t cygpid;
|
2000-09-03 12:16:35 +08:00
|
|
|
public:
|
|
|
|
cygheap_exec_info *moreinfo;
|
2006-12-12 02:55:29 +08:00
|
|
|
int __stdin;
|
|
|
|
int __stdout;
|
|
|
|
char filler[4];
|
2000-09-03 12:16:35 +08:00
|
|
|
|
2011-11-14 09:29:49 +08:00
|
|
|
void cleanup ();
|
|
|
|
child_info_spawn () {};
|
2005-07-17 08:51:03 +08:00
|
|
|
child_info_spawn (child_info_types, bool);
|
2011-10-27 03:42:39 +08:00
|
|
|
void record_children ();
|
|
|
|
void reattach_children ();
|
2005-08-12 00:13:30 +08:00
|
|
|
void *operator new (size_t, void *p) __attribute__ ((nothrow)) {return p;}
|
|
|
|
void set (child_info_types ci, bool b) { new (this) child_info_spawn (ci, b);}
|
2013-01-21 12:34:52 +08:00
|
|
|
void __reg1 handle_spawn ();
|
2011-11-14 09:29:49 +08:00
|
|
|
bool set_saw_ctrl_c ()
|
|
|
|
{
|
|
|
|
if (!has_execed ())
|
|
|
|
return false;
|
|
|
|
flag |= _CI_SAW_CTRL_C;
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
bool signal_myself_exited ()
|
|
|
|
{
|
|
|
|
if (!ev)
|
|
|
|
return false;
|
|
|
|
else
|
|
|
|
{
|
|
|
|
SetEvent (ev);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
}
|
2012-03-21 13:23:13 +08:00
|
|
|
void wait_for_myself ();
|
2011-11-14 09:29:49 +08:00
|
|
|
bool has_execed () const
|
|
|
|
{
|
|
|
|
if (hExeced)
|
|
|
|
return true;
|
|
|
|
if (type != _CH_EXEC)
|
|
|
|
return false;
|
|
|
|
return !!hExeced;
|
|
|
|
}
|
2012-05-15 06:42:56 +08:00
|
|
|
bool get_parent_handle ();
|
2011-11-14 09:29:49 +08:00
|
|
|
bool has_execed_cygwin () const { return iscygwin () && has_execed (); }
|
|
|
|
operator HANDLE& () {return hExeced;}
|
2013-01-21 12:34:52 +08:00
|
|
|
int __reg3 worker (const char *, const char *const *, const char *const [], int,
|
|
|
|
int = -1, int = -1);;
|
2000-09-03 12:16:35 +08:00
|
|
|
};
|
|
|
|
|
2011-11-14 09:29:49 +08:00
|
|
|
extern child_info_spawn ch_spawn;
|
|
|
|
|
|
|
|
#define have_execed ch_spawn.has_execed ()
|
|
|
|
#define have_execed_cygwin ch_spawn.has_execed_cygwin ()
|
|
|
|
|
2004-09-12 11:47:57 +08:00
|
|
|
void __stdcall init_child_info (DWORD, child_info *, HANDLE);
|
2000-09-02 04:54:22 +08:00
|
|
|
|
2005-03-20 05:45:15 +08:00
|
|
|
extern "C" {
|
2002-06-16 05:59:32 +08:00
|
|
|
extern child_info *child_proc_info;
|
2013-04-23 17:44:36 +08:00
|
|
|
extern child_info_spawn *spawn_info asm (_SYMSTR (child_proc_info));
|
|
|
|
extern child_info_fork *fork_info asm (_SYMSTR (child_proc_info));
|
2005-03-20 05:45:15 +08:00
|
|
|
}
|