newlib-cygwin/winsup/cygwin/child_info.h

211 lines
5.2 KiB
C++

/* child_info.h: shared child info for cygwin
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. */
#include <setjmp.h>
enum child_info_types
{
_CH_NADA = 0,
_CH_EXEC = 1,
_CH_SPAWN = 2,
_CH_FORK = 3,
_CH_WHOOPS = 4
};
enum child_status
{
_CI_STRACED = 0x01,
_CI_ISCYGWIN = 0x02,
_CI_SAW_CTRL_C = 0x04,
_CI_SILENTFAIL = 0x08
};
#define OPROC_MAGIC_MASK 0xff00ff00
#define OPROC_MAGIC_GENERIC 0xaf00f000
#ifdef __x86_64__
#define PROC_MAGIC_GENERIC 0xaf00fa64
#else /*!x86_64*/
#define PROC_MAGIC_GENERIC 0xaf00fa32
#endif
#define EXEC_MAGIC_SIZE sizeof(child_info)
/* Change this value if you get a message indicating that it is out-of-sync. */
#define CURR_CHILD_INFO_MAGIC 0xecc930b9U
#include "pinfo.h"
struct cchildren
{
pid_t pid;
pinfo_minimal p;
};
/* 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. */
class child_info
{
public:
DWORD msv_count; // set to 0
DWORD cb; // size of this record
DWORD intro; // improbable string
DWORD magic; // magic number unique to child_info
unsigned short type; // type of record, exec, spawn, fork
init_cygheap *cygheap;
void *cygheap_max;
unsigned char flag;
int retry; // number of times we've tried to start child process
HANDLE rd_proc_pipe;
HANDLE wr_proc_pipe;
HANDLE subproc_ready; // used for synchronization with parent
HANDLE user_h;
HANDLE parent;
DWORD parent_winpid;
DWORD cygheap_reserve_sz;
unsigned fhandler_union_cb;
DWORD exit_code; // process exit code
static int retry_count;// retry count;
child_info (unsigned, child_info_types, bool);
child_info (): subproc_ready (NULL), parent (NULL) {}
~child_info ();
void refresh_cygheap () { cygheap_max = ::cygheap_max; }
void ready (bool);
bool __reg3 sync (int, HANDLE&, DWORD);
DWORD __reg2 proc_retry (HANDLE);
bool isstraced () const {return !!(flag & _CI_STRACED);}
bool iscygwin () const {return !!(flag & _CI_ISCYGWIN);}
bool saw_ctrl_c () const {return !!(flag & _CI_SAW_CTRL_C);}
bool silentfail () const {return !!(flag & _CI_SILENTFAIL);}
void prefork (bool = false);
void cleanup ();
void postfork (pinfo& child)
{
ForceCloseHandle (wr_proc_pipe);
wr_proc_pipe = NULL;
child.set_rd_proc_pipe (rd_proc_pipe);
rd_proc_pipe = NULL;
}
void silentfail (bool f)
{
if (f)
flag |= _CI_SILENTFAIL;
else
flag &= ~_CI_SILENTFAIL;
}
};
class mount_info;
class child_info_fork: public child_info
{
public:
HANDLE forker_finished;// for synchronization with child
jmp_buf jmp; // where child will jump to
void *stackaddr; // DeallocationStack or user-provided allocation address
// of parent thread
void *stacklimit; // StackLimit of parent thread
void *stackbase; // StackBase of parent thread
size_t guardsize; // size of POSIX guard region or (size_t) -1 if
// user stack
char filler[4];
child_info_fork ();
void __reg1 handle_fork ();
bool abort (const char *fmt = NULL, ...);
void alloc_stack ();
};
class fhandler_base;
class cygheap_exec_info
{
public:
int argc;
char **argv;
int envc;
char **envp;
HANDLE myself_pinfo;
sigset_t sigmask;
int nchildren;
cchildren children[0];
static cygheap_exec_info *alloc ();
void record_children ();
void reattach_children (HANDLE);
};
class child_info_spawn: public child_info
{
HANDLE hExeced;
HANDLE ev;
HANDLE sem;
pid_t cygpid;
public:
cygheap_exec_info *moreinfo;
int __stdin;
int __stdout;
char filler[4];
void cleanup ();
child_info_spawn () {};
child_info_spawn (child_info_types, bool);
void record_children ();
void reattach_children ();
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);}
void __reg1 handle_spawn ();
void set_sem (HANDLE _sem)
{
/* Don't leak semaphore handle into exec'ed process. */
SetHandleInformation (sem = _sem, HANDLE_FLAG_INHERIT, 0);
}
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;
}
}
void wait_for_myself ();
bool has_execed () const
{
if (hExeced)
return true;
if (type != _CH_EXEC)
return false;
return !!hExeced;
}
bool get_parent_handle ();
bool has_execed_cygwin () const { return iscygwin () && has_execed (); }
operator HANDLE& () {return hExeced;}
int __reg3 worker (const char *, const char *const *, const char *const [],
int, int = -1, int = -1);
};
extern child_info_spawn ch_spawn;
#define have_execed ch_spawn.has_execed ()
#define have_execed_cygwin ch_spawn.has_execed_cygwin ()
void __stdcall init_child_info (DWORD, child_info *, HANDLE);
extern "C" {
extern child_info *child_proc_info;
extern child_info_spawn *spawn_info asm (_SYMSTR (child_proc_info));
extern child_info_fork *fork_info asm (_SYMSTR (child_proc_info));
}