aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/child_info.h
blob: ddd5b8bc834c157bb40ef16b69537fc3ccdf459e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
/* child_info.h: shared child info for cygwin

   Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2008, 2009, 2011, 2012,
   2013, 2015 Red Hat, Inc.

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
};

#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 0x30ea98f6U

#define NPROCS	256

#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;	// zeroed on < W2K3, set to pseudo-count on Vista
  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);}
  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;
  }
};

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
  bool from_main;	// true if started from parent's main thread
  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;
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 ();
  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));
}