]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/dcrt0.cc
* dcrt0.cc (__main): Force signal synchronization.
[newlib-cygwin.git] / winsup / cygwin / dcrt0.cc
CommitLineData
1fd5e000
CF
1/* dcrt0.cc -- essentially the main() for the Cygwin dll
2
66a83f3e 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
e1212c43 4 2007, 2008, 2009, 2010
66a83f3e 5 Red Hat, Inc.
1fd5e000
CF
6
7This file is part of Cygwin.
8
9This software is a copyrighted work licensed under the terms of the
10Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11details. */
12
4c8d72de 13#include "winsup.h"
ade47a34 14#include "miscfuncs.h"
1fd5e000
CF
15#include <unistd.h>
16#include <stdlib.h>
1fd5e000 17#include "glob.h"
1fd5e000 18#include <ctype.h>
161211d1 19#include <locale.h>
66a83f3e 20#include "environ.h"
bccd5e0d 21#include "sigproc.h"
e2ebe117 22#include "pinfo.h"
9e2baf8d 23#include "cygerrno.h"
f0338f54 24#define NEED_VFORK
95a8465b 25#include "perprocess.h"
ac5561f2 26#include "path.h"
7ac61736 27#include "fhandler.h"
47063f00 28#include "dtable.h"
0381fec6 29#include "cygheap.h"
77f4a250 30#include "child_info_magic.h"
8cb359d9 31#include "cygtls.h"
29ac7f89 32#include "shared_info.h"
f0338f54 33#include "cygwin_version.h"
f0338f54 34#include "dll_init.h"
2d1d1eb1 35#include "heap.h"
8c4fc35e 36#include "tls_pbuf.h"
98a97ac6 37#include "exception.h"
53c24915 38#include "cygxdr.h"
893a8b78 39#include "ntdll.h"
1fd5e000
CF
40
41#define MAX_AT_FILE_LEVEL 10
42
0312ede4 43#define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
14a3bc2f 44
66a83f3e 45extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
fac0681d
CF
46extern "C" void __sinit (_reent *);
47
66a83f3e
CF
48static int NO_COPY envc;
49static char NO_COPY **envp;
179cae11 50
66a83f3e 51static char title_buf[TITLESIZE + 1];
1fd5e000 52
3c4f2024
CF
53bool NO_COPY jit_debug;
54
1fd5e000 55static void
3ac78fd6 56do_global_dtors ()
1fd5e000 57{
dda06573
CF
58 void (**pfunc) () = user_data->dtors;
59 if (pfunc)
1fd5e000 60 {
dda06573 61 user_data->dtors = NULL;
1fd5e000
CF
62 while (*++pfunc)
63 (*pfunc) ();
64 }
65}
66
67static void __stdcall
68do_global_ctors (void (**in_pfunc)(), int force)
69{
5d970405 70 if (!force && in_forkee)
29d52c8a 71 return; // inherit constructed stuff from parent pid
1fd5e000
CF
72
73 /* Run ctors backwards, so skip the first entry and find how many
74 there are, then run them. */
75
29d52c8a 76 void (**pfunc) () = in_pfunc;
1fd5e000
CF
77
78 while (*++pfunc)
79 ;
80 while (--pfunc > in_pfunc)
81 (*pfunc) ();
1fd5e000
CF
82}
83
1fd5e000 84/*
052e90e9
CF
85 * Replaces @file in the command line with the contents of the file.
86 * There may be multiple @file's in a single command line
87 * A \@file is replaced with @file so that echo \@foo would print
88 * @foo and not the contents of foo.
1fd5e000 89 */
2e008fb9 90static bool __stdcall
eafa31fb 91insert_file (char *name, char *&cmd)
1fd5e000
CF
92{
93 HANDLE f;
94 DWORD size;
8c4fc35e
CV
95 tmp_pathbuf tp;
96
97 PWCHAR wname = tp.w_get ();
023266aa 98 sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
8c4fc35e
CV
99 f = CreateFileW (wname,
100 GENERIC_READ, /* open for reading */
101 FILE_SHARE_READ, /* share for reading */
102 &sec_none_nih, /* default security */
103 OPEN_EXISTING, /* existing file only */
104 FILE_ATTRIBUTE_NORMAL,/* normal file */
105 NULL); /* no attr. template */
1fd5e000
CF
106
107 if (f == INVALID_HANDLE_VALUE)
108 {
109 debug_printf ("couldn't open file '%s', %E", name);
2e008fb9 110 return false;
1fd5e000
CF
111 }
112
113 /* This only supports files up to about 4 billion bytes in
114 size. I am making the bold assumption that this is big
115 enough for this feature */
116 size = GetFileSize (f, NULL);
117 if (size == 0xFFFFFFFF)
118 {
119 debug_printf ("couldn't get file size for '%s', %E", name);
2e008fb9 120 return false;
1fd5e000
CF
121 }
122
123 int new_size = strlen (cmd) + size + 2;
124 char *tmp = (char *) malloc (new_size);
125 if (!tmp)
126 {
127 debug_printf ("malloc failed, %E");
2e008fb9 128 return false;
1fd5e000
CF
129 }
130
131 /* realloc passed as it should */
132 DWORD rf_read;
133 BOOL rf_result;
134 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
135 CloseHandle (f);
136 if (!rf_result || (rf_read != size))
137 {
138 debug_printf ("ReadFile failed, %E");
2e008fb9 139 return false;
1fd5e000
CF
140 }
141
142 tmp[size++] = ' ';
143 strcpy (tmp + size, cmd);
144 cmd = tmp;
2e008fb9 145 return true;
1fd5e000
CF
146}
147
148static inline int
149isquote (char c)
150{
151 char ch = c;
152 return ch == '"' || ch == '\'';
153}
154
155/* Step over a run of characters delimited by quotes */
8e382d80 156static /*__inline*/ char *
9cec3d45 157quoted (char *cmd, int winshell)
1fd5e000
CF
158{
159 char *p;
160 char quote = *cmd;
161
b0e82b74 162 if (!winshell)
1fd5e000 163 {
b0e82b74
CF
164 char *p;
165 strcpy (cmd, cmd + 1);
de9e39f7 166 if (*(p = strechr (cmd, quote)))
b0e82b74 167 strcpy (p, p + 1);
99d7d12a 168 return p;
1fd5e000
CF
169 }
170
4eafa56e 171 const char *s = quote == '\'' ? "'" : "\\\"";
b0e82b74
CF
172 /* This must have been run from a Windows shell, so preserve
173 quotes for globify to play with later. */
4eafa56e
CF
174 while (*cmd && *++cmd)
175 if ((p = strpbrk (cmd, s)) == NULL)
b0e82b74
CF
176 {
177 cmd = strchr (cmd, '\0'); // no closing quote
178 break;
179 }
b0e82b74
CF
180 else if (*p == '\\')
181 cmd = ++p;
4eafa56e 182 else if (quote == '"' && p[1] == '"')
b0e82b74
CF
183 {
184 *p = '\\';
185 cmd = ++p; // a quoted quote
186 }
187 else
188 {
189 cmd = p + 1; // point to after end
190 break;
191 }
192 return cmd;
1fd5e000
CF
193}
194
195/* Perform a glob on word if it contains wildcard characters.
196 Also quote every character between quotes to force glob to
197 treat the characters literally. */
198static int __stdcall
199globify (char *word, char **&argv, int &argc, int &argvlen)
200{
201 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
202 return 0;
203
204 int n = 0;
205 char *p, *s;
75858e8a 206 int dos_spec = isdrive (word);
0312ede4 207 if (!dos_spec && isquote (*word) && word[1] && word[2])
75858e8a 208 dos_spec = isdrive (word + 1);
1fd5e000
CF
209
210 /* We'll need more space if there are quoting characters in
211 word. If that is the case, doubling the size of the
212 string should provide more than enough space. */
213 if (strpbrk (word, "'\""))
214 n = strlen (word);
215 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
216
217 /* Fill pattern with characters from word, quoting any
218 characters found within quotes. */
219 for (p = pattern, s = word; *s != '\000'; s++, p++)
220 if (!isquote (*s))
221 {
222 if (dos_spec && *s == '\\')
223 *p++ = '\\';
224 *p = *s;
225 }
226 else
227 {
228 char quote = *s;
229 while (*++s && *s != quote)
230 {
25ba8f30 231 if (dos_spec || *s != '\\')
c845acff 232 /* nothing */;
c845acff 233 else if (s[1] == quote || s[1] == '\\')
1fd5e000
CF
234 s++;
235 *p++ = '\\';
855762d6 236 size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
0351fbd5
CV
237 if (cnt <= 1 || cnt == (size_t)-1)
238 *p++ = *s;
239 else
240 {
241 --s;
242 while (cnt-- > 0)
243 *p++ = *++s;
244 }
1fd5e000
CF
245 }
246 if (*s == quote)
247 p--;
248 if (*s == '\0')
249 break;
250 }
251
252 *p = '\0';
253
254 glob_t gl;
255 gl.gl_offs = 0;
256
257 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
258 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
259 return 0;
260
261 /* Allocate enough space in argv for the matched filenames. */
262 n = argc;
263 if ((argc += gl.gl_pathc) > argvlen)
264 {
265 argvlen = argc + 10;
266 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
267 }
268
269 /* Copy the matched filenames to argv. */
270 char **gv = gl.gl_pathv;
271 char **av = argv + n;
272 while (*gv)
273 {
f70389b5 274 debug_printf ("argv[%d] = '%s'", n++, *gv);
1fd5e000
CF
275 *av++ = *gv++;
276 }
277
278 /* Clean up after glob. */
279 free (gl.gl_pathv);
280 return 1;
281}
282
283/* Build argv, argc from string passed from Windows. */
284
285static void __stdcall
286build_argv (char *cmd, char **&argv, int &argc, int winshell)
287{
288 int argvlen = 0;
1fd5e000
CF
289 int nesting = 0; // monitor "nesting" from insert_file
290
291 argc = 0;
292 argvlen = 0;
293 argv = NULL;
294
295 /* Scan command line until there is nothing left. */
296 while (*cmd)
297 {
298 /* Ignore spaces */
299 if (issep (*cmd))
300 {
301 cmd++;
302 continue;
303 }
304
305 /* Found the beginning of an argument. */
306 char *word = cmd;
307 char *sawquote = NULL;
308 while (*cmd)
309 {
310 if (*cmd != '"' && (!winshell || *cmd != '\''))
311 cmd++; // Skip over this character
312 else
313 /* Skip over characters until the closing quote */
314 {
315 sawquote = cmd;
2768430b 316 cmd = quoted (cmd, winshell && argc > 0);
1fd5e000
CF
317 }
318 if (issep (*cmd)) // End of argument if space
319 break;
320 }
321 if (*cmd)
322 *cmd++ = '\0'; // Terminate `word'
323
324 /* Possibly look for @file construction assuming that this isn't
325 the very first argument and the @ wasn't quoted */
326 if (argc && sawquote != word && *word == '@')
327 {
328 if (++nesting > MAX_AT_FILE_LEVEL)
329 api_fatal ("Too many levels of nesting for %s", word);
eafa31fb 330 if (insert_file (word, cmd))
1fd5e000 331 continue; // There's new stuff in cmd now
1fd5e000
CF
332 }
333
334 /* See if we need to allocate more space for argv */
335 if (argc >= argvlen)
336 {
337 argvlen = argc + 10;
338 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
339 }
340
341 /* Add word to argv file after (optional) wildcard expansion. */
342 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
343 {
f70389b5 344 debug_printf ("argv[%d] = '%s'", argc, word);
1fd5e000
CF
345 argv[argc++] = word;
346 }
347 }
348
349 argv[argc] = NULL;
b0e82b74
CF
350
351 debug_printf ("argc %d", argc);
1fd5e000
CF
352}
353
354/* sanity and sync check */
355void __stdcall
356check_sanity_and_sync (per_process *p)
357{
358 /* Sanity check to make sure developers didn't change the per_process */
359 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
360 /* about changing it]. */
361 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
c16548b2 362 api_fatal ("per_process sanity check failed");
1fd5e000
CF
363
364 /* Make sure that the app and the dll are in sync. */
365
366 /* Complain if older than last incompatible change */
367 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
368 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
369 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
370
371 /* magic_biscuit != 0 if using the old style version numbering scheme. */
372 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
373 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
374 p->magic_biscuit, SIZEOF_PER_PROCESS);
375
376 /* Complain if incompatible API changes made */
876083f3
CF
377 if (p->api_major > cygwin_version.api_major)
378 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
1fd5e000 379 p->api_major, cygwin_version.api_major);
284c5ea0
CF
380
381 /* This is a kludge to work around a version of _cygwin_common_crt0
382 which overwrote the cxx_malloc field with the local DLL copy.
383 Hilarity ensues if the DLL is not loaded while the process
384 is forking. */
385 __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
1fd5e000
CF
386}
387
6ea3e429 388child_info NO_COPY *child_proc_info = NULL;
1fd5e000 389
39fc0d36 390#define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
e13ea334 391
9dbb0bc3
CF
392void
393child_info_fork::alloc_stack_hard_way (volatile char *b)
1fd5e000
CF
394{
395 void *new_stack_pointer;
396 MEMORY_BASIC_INFORMATION m;
b0e82b74
CF
397 void *newbase;
398 int newlen;
39fc0d36 399 bool guard;
1fd5e000 400
1a6aafd0
CF
401 if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
402 api_fatal ("fork: couldn't get stack info, %E");
403
404 LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
405
9dbb0bc3 406 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
b0e82b74
CF
407 {
408 newbase = curbot;
9dbb0bc3 409 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
39fc0d36 410 guard = false;
b0e82b74
CF
411 }
412 else
413 {
39fc0d36
CF
414 newbase = (LPBYTE) stacktop - (128 * 1024);
415 newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
416 guard = true;
b0e82b74 417 }
39fc0d36 418
b0e82b74 419 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
1fd5e000 420 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
9dbb0bc3 421 stacktop, stackbottom);
39fc0d36 422 new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
9dbb0bc3 423 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
1fd5e000
CF
424 PAGE_EXECUTE_READWRITE))
425 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
9dbb0bc3 426 new_stack_pointer, stacksize);
1fd5e000
CF
427 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
428 api_fatal ("fork: couldn't get new stack info, %E");
39fc0d36
CF
429
430 if (guard)
b0e82b74 431 {
39fc0d36 432 m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
b0e82b74 433 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
a54ad580 434 CYGWIN_GUARD))
b0e82b74
CF
435 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
436 m.BaseAddress);
437 }
1fd5e000
CF
438 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
439 api_fatal ("fork: couldn't get new stack info, %E");
9dbb0bc3 440 stacktop = m.BaseAddress;
c21e74cc 441 b[0] = '\0';
1fd5e000
CF
442}
443
280fdd0b
CF
444void *getstack (void *) __attribute__ ((noinline));
445volatile char *
e7f6a31b 446getstack (volatile char * volatile p)
280fdd0b 447{
e7f6a31b
CF
448 *p ^= 1;
449 *p ^= 1;
280fdd0b
CF
450 return p - 4096;
451}
452
1fd5e000
CF
453/* extend the stack prior to fork longjmp */
454
9dbb0bc3
CF
455void
456child_info_fork::alloc_stack ()
1fd5e000 457{
e7f6a31b 458 volatile char * volatile esp;
280fdd0b 459 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
9dbb0bc3
CF
460 if (_tlsbase != stackbottom)
461 alloc_stack_hard_way (esp);
c21e74cc 462 else
280fdd0b 463 {
9dbb0bc3
CF
464 char *st = (char *) stacktop - 4096;
465 while (_tlstop >= st)
280fdd0b 466 esp = getstack (esp);
9dbb0bc3 467 stacksize = 0;
280fdd0b 468 }
1fd5e000
CF
469}
470
35016286 471extern "C" void
2d1d1eb1
CF
472break_here ()
473{
35016286
CF
474 static int NO_COPY sent_break;
475 if (!sent_break++)
476 DebugBreak ();
2d1d1eb1
CF
477 debug_printf ("break here");
478}
2d1d1eb1 479
1fd5e000 480static void
0e061ecf 481initial_env ()
1fd5e000 482{
5ab0b5cf 483 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
d795119c 484 _cygwin_testing = 1;
0e061ecf 485
2d1d1eb1 486#ifdef DEBUGGING
5ab0b5cf 487 char buf[NT_MAX_PATH];
2d1d1eb1 488 DWORD len;
d795119c 489
5ab0b5cf 490 if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
2d1d1eb1
CF
491 {
492 DWORD ms = atoi (buf);
1feea0bf 493 console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
f6936c48 494 Sleep (ms);
5d970405
CF
495 if (!strace.active () && !dynamically_loaded)
496 strace.hello ();
2d1d1eb1 497 }
5ab0b5cf 498 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
2d1d1eb1 499 {
7b4b41ab
CV
500 char buf1[NT_MAX_PATH];
501 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
2d1d1eb1
CF
502 strlwr (buf1);
503 strlwr (buf);
491e84c6 504 char *p = strpbrk (buf, ":=");
2d1d1eb1
CF
505 if (!p)
506 p = (char *) "gdb.exe -nw";
507 else
508 *p++ = '\0';
509 if (strstr (buf1, buf))
510 {
511 error_start_init (p);
3c4f2024 512 jit_debug = true;
2d1d1eb1 513 try_to_debug ();
0e061ecf 514 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
2d1d1eb1
CF
515 break_here ();
516 }
517 }
518#endif
1fd5e000 519
2d1d1eb1 520}
b0e82b74 521
1cd8ccec
CF
522child_info *
523get_cygwin_startup_info ()
2d1d1eb1 524{
1cd8ccec 525 STARTUPINFO si;
fe4283af 526
2d1d1eb1 527 GetStartupInfo (&si);
1cd8ccec 528 child_info *res = (child_info *) si.lpReserved2;
c6674b53 529
1cd8ccec 530 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
c16548b2 531 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
1cd8ccec 532 res = NULL;
2d1d1eb1
CF
533 else
534 {
1cd8ccec
CF
535 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
536 multiple_cygwin_problem ("proc intro", res->intro, 0);
1cd8ccec
CF
537 else if (res->cygheap != (void *) &_cygheap_start)
538 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
2d1d1eb1 539 (DWORD) &_cygheap_start);
1cd8ccec 540
2d1d1eb1 541 unsigned should_be_cb = 0;
1cd8ccec 542 switch (res->type)
2d1d1eb1
CF
543 {
544 case _PROC_FORK:
5d970405 545 in_forkee = true;
2d1d1eb1
CF
546 should_be_cb = sizeof (child_info_fork);
547 /* fall through */;
548 case _PROC_SPAWN:
549 case _PROC_EXEC:
550 if (!should_be_cb)
54dd79bb 551 should_be_cb = sizeof (child_info_spawn);
1cd8ccec
CF
552 if (should_be_cb != res->cb)
553 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
554 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
555 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
c1494e03 556 if (res->isstraced ())
5d970405
CF
557 {
558 res->ready (false);
5d970405 559 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
084ea510 560 yield ();
5d970405
CF
561 strace.hello ();
562 }
2380dfe1 563 break;
2d1d1eb1 564 default:
1cd8ccec 565 system_printf ("unknown exec type %d", res->type);
2d1d1eb1
CF
566 /* intentionally fall through */
567 case _PROC_WHOOPS:
1cd8ccec 568 res = NULL;
2d1d1eb1
CF
569 break;
570 }
571 }
572
1cd8ccec
CF
573 return res;
574}
575
ad02bb70
CF
576#define dll_data_start &_data_start__
577#define dll_data_end &_data_end__
578#define dll_bss_start &_bss_start__
579#define dll_bss_end &_bss_end__
580
581void
5d970405 582child_info_fork::handle_fork ()
ad02bb70 583{
ad02bb70 584 cygheap_fixup_in_child (false);
71f53a2f 585 memory_init (false);
9ac42168 586 myself.thisproc (NULL);
12b33712
CF
587 myself->uid = cygheap->user.real_uid;
588 myself->gid = cygheap->user.real_gid;
589
5d970405 590 child_copy (parent, false,
ad02bb70
CF
591 "dll data", dll_data_start, dll_data_end,
592 "dll bss", dll_bss_start, dll_bss_end,
593 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
594 NULL);
27f564e9
CF
595
596 /* Do the relocations here. These will actually likely be overwritten by the
597 below child_copy but we do them here in case there is a read-only section
598 which does not get copied by fork. */
599 _pei386_runtime_relocator (user_data);
600
ad02bb70
CF
601 /* step 2 now that the dll has its heap filled in, we can fill in the
602 user's data and bss since user_data is now filled out. */
5d970405 603 child_copy (parent, false,
ad02bb70
CF
604 "data", user_data->data_start, user_data->data_end,
605 "bss", user_data->bss_start, user_data->bss_end,
606 NULL);
607
5d970405 608 if (fixup_mmaps_after_fork (parent))
ad02bb70
CF
609 api_fatal ("recreate_mmaps_after_fork_failed");
610}
611
c1494e03
CF
612void
613child_info_spawn::handle_spawn ()
614{
a998dd70 615 extern void fixup_lockf_after_exec ();
c1494e03
CF
616 HANDLE h;
617 cygheap_fixup_in_child (true);
71f53a2f 618 memory_init (false);
c1494e03 619 if (!moreinfo->myself_pinfo ||
f16706de
CV
620 !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
621 GetCurrentProcess (), &h, 0,
c1494e03
CF
622 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
623 h = NULL;
9ac42168 624 myself.thisproc (h);
c1494e03
CF
625 __argc = moreinfo->argc;
626 __argv = moreinfo->argv;
627 envp = moreinfo->envp;
628 envc = moreinfo->envc;
629 if (!dynamically_loaded)
630 cygheap->fdtab.fixup_after_exec ();
c16548b2
CF
631 if (__stdin >= 0)
632 cygheap->fdtab.move_fd (__stdin, 0);
633 if (__stdout >= 0)
634 cygheap->fdtab.move_fd (__stdout, 1);
5558de95 635 cygheap->user.groups.clear_supp ();
c16548b2 636
578e142a 637 ready (true);
2346864a
CF
638
639 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
640 handles might get confused. */
641 CloseHandle (child_proc_info->parent);
642 child_proc_info->parent = NULL;
643
c1494e03
CF
644 signal_fixup_after_exec ();
645 if (moreinfo->old_title)
646 {
647 old_title = strcpy (title_buf, moreinfo->old_title);
648 cfree (moreinfo->old_title);
649 }
a998dd70 650 fixup_lockf_after_exec ();
c1494e03
CF
651}
652
06281845
CV
653#if 0
654/* Setting the TS-aware flag in the application's PE header is sufficient.
655 Just keep this in as a reminder. */
656
babd4a9c
CV
657static DEP_SYSTEM_POLICY_TYPE dep_system_policy = (DEP_SYSTEM_POLICY_TYPE) -1;
658
659static void
660disable_dep ()
661{
662 DWORD ppolicy;
663 BOOL perm;
664
665 if (dep_system_policy < 0)
666 {
667 dep_system_policy = GetSystemDEPPolicy ();
668 debug_printf ("DEP System Policy: %d", (int) dep_system_policy);
669 }
670 if (dep_system_policy < OptIn)
671 return;
f16706de 672 if (!GetProcessDEPPolicy (GetCurrentProcess (), &ppolicy, &perm))
babd4a9c
CV
673 {
674 debug_printf ("GetProcessDEPPolicy: %E");
675 return;
676 }
677 debug_printf ("DEP Process Policy: %d (permanent = %d)", ppolicy, perm);
678 if (ppolicy > 0 && !perm && !SetProcessDEPPolicy (0))
679 debug_printf ("SetProcessDEPPolicy: %E");
680}
06281845 681#endif
babd4a9c 682
893a8b78
CV
683/* Retrieve and store system directory for later use. Note that the
684 directory is stored with a trailing backslash! */
685static void
686init_windows_system_directory ()
687{
688 windows_system_directory_length =
689 GetSystemDirectoryW (windows_system_directory, MAX_PATH);
690 if (windows_system_directory_length == 0)
691 api_fatal ("can't find windows system directory");
692 windows_system_directory[windows_system_directory_length++] = L'\\';
693 windows_system_directory[windows_system_directory_length] = L'\0';
694}
695
1cd8ccec
CF
696void __stdcall
697dll_crt0_0 ()
698{
893a8b78 699 init_windows_system_directory ();
2b91e0da 700 init_global_security ();
bbca1e4c
CF
701 initial_env ();
702
346cdb43 703 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
d4d63ebf 704
82c925af 705 lock_process::init ();
280fdd0b
CF
706 _impure_ptr = _GLOBAL_REENT;
707 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
708 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
709 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
710 _impure_ptr->_current_locale = "C";
5d970405
CF
711 user_data->impure_ptr = _impure_ptr;
712 user_data->impure_ptr_ptr = &_impure_ptr;
1cd8ccec 713
1b71ce00
CV
714 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
715 GetCurrentProcess (), &hMainThread,
716 0, false, DUPLICATE_SAME_ACCESS);
717
f16706de 718 OpenProcessToken (GetCurrentProcess (), MAXIMUM_ALLOWED, &hProcToken);
5fbf573c 719 set_cygwin_privileges (hProcToken);
1cd8ccec 720
2d1d1eb1 721 device::init ();
2d1d1eb1
CF
722 do_global_ctors (&__CTOR_LIST__, 1);
723 cygthread::init ();
b0e82b74 724
1cd8ccec 725 child_proc_info = get_cygwin_startup_info ();
fdb28b5e 726 if (!child_proc_info)
71f53a2f 727 memory_init (true);
fdb28b5e 728 else
b0e82b74 729 {
1cd8ccec 730 cygwin_user_h = child_proc_info->user_h;
77f4a250 731 switch (child_proc_info->type)
b0e82b74 732 {
57013c31 733 case _PROC_FORK:
5d970405 734 fork_info->handle_fork ();
b0e82b74 735 break;
57013c31 736 case _PROC_SPAWN:
57013c31 737 case _PROC_EXEC:
c1494e03 738 spawn_info->handle_spawn ();
b0e82b74
CF
739 break;
740 }
741 }
1fd5e000 742
0ce97eb4
CF
743 user_data->threadinterface->Init ();
744
e431827c 745 _cygtls::init ();
2d1d1eb1
CF
746
747 /* Initialize events */
748 events_init ();
71d59a92 749 tty_list::init_session ();
2d1d1eb1 750
06281845
CV
751#if 0
752 /* Setting the TS-aware flag in the application's PE header is sufficient.
753 Just keep this in as a reminder. */
babd4a9c 754
06281845 755 /* The disable_dep function disables DEP for all Cygwin processes if
babd4a9c
CV
756 the process runs on a Windows Server 2008 with Terminal Services
757 installed. This combination (TS+DEP) breaks *some* Cygwin
758 applications. The Terminal Service specific DLL tsappcmp.dll
759 changes the page protection of some pages in the application's text
760 segment from PAGE_EXECUTE_WRITECOPY to PAGE_WRITECOPY for no
761 apparent reason. This occurs before any Cygwin or applicaton code
762 had a chance to run. MS has no explanation for this so far, but is
763 rather busy trying to avoid giving support for this problem (as of
764 2008-11-11).
765
766 Unfortunately disabling DEP seems to have a not negligible
767 performance hit. In the long run, either MS has to fix their
768 problem, or we have to find a better workaround, if any exists.
769 Idle idea: Adding EXECUTE protection to all text segment pages? */
770 if (wincap.ts_has_dep_problem ())
771 disable_dep ();
06281845 772#endif
babd4a9c 773
6c6eb02b
CF
774 /* Initialize signal processing here, early, in the hopes that the creation
775 of a thread early in the process will cause more predictability in memory
776 layout for the main thread. */
b6473313 777 if (!wincap.has_buggy_thread_startup () && !dynamically_loaded)
6c6eb02b
CF
778 sigproc_init ();
779
5d970405 780 debug_printf ("finished dll_crt0_0 initialization");
2d1d1eb1
CF
781}
782
783/* Take over from libc's crt0.o and start the application. Note the
784 various special cases when Cygwin DLL is being runtime loaded (as
785 opposed to being link-time loaded by Cygwin apps) from a non
786 cygwin app via LoadLibrary. */
2346864a
CF
787void
788dll_crt0_1 (void *)
2d1d1eb1 789{
0ca6c6b8
CV
790 extern void initial_setlocale ();
791
b6473313 792 if (wincap.has_buggy_thread_startup () || dynamically_loaded)
58569753 793 sigproc_init ();
2d1d1eb1 794 check_sanity_and_sync (user_data);
e643b202 795
038af334
CF
796 /* Initialize malloc and then call user_shared_initialize since it relies
797 on a functioning malloc and it's possible that the user's program may
798 have overridden malloc. We only know about that at this stage,
799 unfortunately. */
800 malloc_init ();
cef5dfd7 801 user_shared->initialize ();
e643b202 802
6a7bea70
CF
803#ifdef CGF
804 int i = 0;
0d339267
CF
805 const int n = 2 * 1024 * 1024;
806 while (i--)
807 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
6a7bea70 808#endif
2d1d1eb1 809
1b71ce00
CV
810 ProtectHandle (hMainThread);
811
9749fd08
CV
812 cygheap->cwd.init ();
813
9a4d574b 814 /* Initialize pthread mainthread when not forked and it is safe to call new,
c8fa3426 815 otherwise it is reinitalized in fixup_after_fork */
5d970405 816 if (!in_forkee)
27f564e9
CF
817 {
818 pthread::init_mainthread ();
819 _pei386_runtime_relocator (user_data);
820 }
f8c8e13b 821
b9621e8d
CF
822#ifdef DEBUGGING
823 strace.microseconds ();
824#endif
825
12b33712 826 create_signal_arrived (); /* FIXME: move into wait_sig? */
a9c46162 827
3d0ba393
CF
828 /* Initialize debug muto, if DLL is built with --enable-debugging.
829 Need to do this before any helper threads start. */
830 debug_init ();
831
f7239090 832#ifdef NEWVFORK
0381fec6 833 cygheap->fdtab.vfork_child_fixup ();
9661a0c8 834 main_vfork = vfork_storage.create ();
f7239090 835#endif
6e8f36bc 836
166b2571 837 cygbench ("pre-forkee");
5d970405 838 if (in_forkee)
1fd5e000
CF
839 {
840 /* If we've played with the stack, stacksize != 0. That means that
841 fork() was invoked from other than the main thread. Make sure that
842 frame pointer is referencing the new stack so that the OS knows what
843 to do when it needs to increase the size of the stack.
844
845 NOTE: Don't do anything that involves the stack until you've completed
846 this step. */
b0e82b74 847 if (fork_info->stacksize)
1fd5e000 848 {
c350feda
CF
849 _tlsbase = (char *) fork_info->stackbottom;
850 _tlstop = (char *) fork_info->stacktop;
1fd5e000 851 }
39fc0d36 852
d584454c 853 longjmp (fork_info->jmp, true);
1fd5e000
CF
854 }
855
b6473313
CF
856 __sinit (_impure_ptr);
857
84aeff41
CF
858#ifdef DEBUGGING
859 {
860 extern void fork_init ();
861 fork_init ();
862 }
863#endif
81010d21 864 pinfo_init (envp, envc);
84aeff41 865
1fd5e000 866 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
12b33712 867 old_title = title_buf;
1fd5e000 868
0381fec6 869 /* Allocate cygheap->fdtab */
e2ebe117 870 dtable_init ();
1fd5e000 871
81010d21
CF
872 uinfo_init (); /* initialize user info */
873
1fd5e000 874 /* Connect to tty. */
71d59a92 875 tty::init_session ();
1fd5e000 876
1afba8e5
CF
877 /* Set internal locale to the environment settings. */
878 initial_setlocale ();
879
b0e82b74 880 if (!__argc)
1fd5e000 881 {
1597484c 882 PWCHAR wline = GetCommandLineW ();
6542ddc3 883 size_t size = sys_wcstombs (NULL, 0, wline);
1597484c
CV
884 char *line = (char *) alloca (size);
885 sys_wcstombs (line, size, wline);
ee1d77e4 886
b0e82b74
CF
887 /* Scan the command line and build argv. Expand wildcards if not
888 called from another cygwin process. */
889 build_argv (line, __argv, __argc,
890 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
891
892 /* Convert argv[0] to posix rules if it's currently blatantly
893 win32 style. */
894 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
895 {
7b4b41ab 896 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
edab6053
CV
897 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
898 new_argv0, NT_MAX_PATH);
76832a5b 899 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
b0e82b74 900 }
1fd5e000
CF
901 }
902
3ef50005 903 __argc_safe = __argc;
b0e82b74
CF
904 if (user_data->premain[0])
905 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
95a8465b 906 user_data->premain[i] (__argc, __argv, user_data);
b0e82b74 907
1ac6d1a1 908 /* Set up standard fds in file descriptor table. */
083abe54 909 cygheap->fdtab.stdio_init ();
1ac6d1a1 910
1fd5e000 911 /* Set up __progname for getopt error call. */
eba23038
CV
912 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
913 ++__progname;
914 else
915 __progname = __argv[0];
916 if (__progname)
917 {
918 char *cp = strchr (__progname, '\0') - 4;
c69d873f 919 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
eba23038
CV
920 *cp = '\0';
921 }
1fd5e000 922
1dc16fc7
CF
923 /* Set new console title if appropriate. */
924
925 if (display_title && !dynamically_loaded)
926 {
927 char *cp = __progname;
928 if (strip_title_path)
929 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
930 if (isdirsep (*ptr))
931 cp = ptr + 1;
932 set_console_title (cp);
933 }
934
53c24915 935 (void) xdr_set_vprintf (&cygxdr_vwarnx);
e431827c 936 cygwin_finished_initializing = true;
2eb392bd
CF
937 /* Call init of loaded dlls. */
938 dlls.init ();
1fd5e000 939
14a3bc2f 940 /* Execute any specified "premain" functions */
737a86d3 941 if (user_data->premain[PREMAIN_LEN / 2])
14a3bc2f 942 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
95a8465b 943 user_data->premain[i] (__argc, __argv, user_data);
14a3bc2f 944
6c6eb02b 945 set_errno (0);
2eb392bd 946
5bc584ba 947 if (dynamically_loaded)
6c6eb02b 948 return;
5bc584ba 949
6ccb6bcf 950 /* Disable case-insensitive globbing */
2e008fb9 951 ignore_case_with_glob = false;
6ccb6bcf 952
b0e82b74 953 MALLOC_CHECK;
166b2571 954 cygbench (__progname);
29d52c8a 955
b1d9a0bd 956 ld_preload ();
41d184bb
CV
957 /* Per POSIX set the default application locale back to "C". */
958 _setlocale_r (_REENT, LC_CTYPE, "C");
6c6eb02b 959
64b30629 960 if (user_data->main)
a586e5b6 961 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
b23b1716
CF
962 __asm__ (" \n\
963 .global __cygwin_exit_return \n\
964__cygwin_exit_return: \n\
965");
1fd5e000
CF
966}
967
72f8054f
CF
968extern "C" void __stdcall
969_dll_crt0 ()
1fd5e000 970{
2eb392bd 971 main_environ = user_data->envptr;
5d970405 972 if (in_forkee)
b6473313 973 fork_info->alloc_stack ();
5e0f482f 974
b6473313 975 _main_tls = &_my_tls;
38229bcd 976 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
1fd5e000
CF
977}
978
14a3bc2f
CF
979void
980dll_crt0 (per_process *uptr)
981{
982 /* Set the local copy of the pointer into the user space. */
5d970405 983 if (!in_forkee && uptr && uptr != user_data)
737a86d3
CF
984 {
985 memcpy (user_data, uptr, per_process_overwrite);
22a1a24f 986 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
737a86d3 987 }
72f8054f 988 _dll_crt0 ();
14a3bc2f
CF
989}
990
6e780c8b 991/* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
4fe79f1c
CF
992 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
993 calling this function, and that storage must not be overwritten until you
994 unload cygwin1.dll, as it is used for _my_tls. It is best to load
995 cygwin1.dll before spawning any additional threads in your process.
1cd06583 996
4fe79f1c
CF
997 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
998 from MSVC and non-cygwin MinGW applications. */
737a86d3 999extern "C" void
48b87053
DD
1000cygwin_dll_init ()
1001{
48b87053
DD
1002 static char **envp;
1003 static int _fmode;
48b87053 1004
48b87053
DD
1005 user_data->magic_biscuit = sizeof (per_process);
1006
48b87053
DD
1007 user_data->envptr = &envp;
1008 user_data->fmode_ptr = &_fmode;
1009
29b35f7a 1010 _dll_crt0 ();
48b87053
DD
1011}
1012
1fd5e000
CF
1013extern "C" void
1014__main (void)
1015{
900f2071 1016 /* Ordering is critical here. DLL ctors have already been
824d8518 1017 run as they were being loaded, so we should stack the
900f2071
CV
1018 queued call to DLL dtors now. */
1019 atexit (dll_global_dtors);
2e008fb9 1020 do_global_ctors (user_data->ctors, false);
b6473313
CF
1021 /* Now we have run global ctors, register their dtors.
1022
1023 At exit, global dtors will run first, so the app can still
900f2071
CV
1024 use shared library functions while terminating; then the
1025 DLLs will be destroyed; finally newlib will shut down stdio
1026 and terminate itself. */
b6473313 1027 atexit (do_global_dtors);
b6473313 1028 sig_dispatch_pending (true);
1fd5e000
CF
1029}
1030
3400b4fc 1031void __stdcall
1fd5e000
CF
1032do_exit (int status)
1033{
ce40c6ba
CF
1034 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1035
f7239090 1036#ifdef NEWVFORK
ce40c6ba
CF
1037 vfork_save *vf = vfork_storage.val ();
1038 if (vf != NULL && vf->pid < 0)
1039 {
1040 exit_state = ES_NOT_EXITING;
1041 vf->restore_exit (status);
1042 }
f7239090 1043#endif
ce40c6ba 1044
267e201d 1045 lock_process until_exit (true);
b739751d 1046
3400b4fc
CF
1047 if (exit_state < ES_EVENTS_TERMINATE)
1048 {
1049 exit_state = ES_EVENTS_TERMINATE;
1050 events_terminate ();
1051 }
1052
1fd5e000 1053 UINT n = (UINT) status;
c4ec64d7
CF
1054 if (exit_state < ES_THREADTERM)
1055 {
1056 exit_state = ES_THREADTERM;
1057 cygthread::terminate ();
1058 }
1059
1fd5e000
CF
1060 if (exit_state < ES_SIGNAL)
1061 {
1062 exit_state = ES_SIGNAL;
8cb359d9
CF
1063 signal (SIGCHLD, SIG_IGN);
1064 signal (SIGHUP, SIG_IGN);
1065 signal (SIGINT, SIG_IGN);
1066 signal (SIGQUIT, SIG_IGN);
1fd5e000
CF
1067 }
1068
166b2571 1069 if (exit_state < ES_CLOSEALL)
1fd5e000
CF
1070 {
1071 exit_state = ES_CLOSEALL;
f9fb1149 1072 close_all_files ();
1fd5e000
CF
1073 }
1074
3f5046a5 1075 myself->stopsig = 0;
1fd5e000 1076
3f5046a5
CF
1077 if (exit_state < ES_HUP_PGRP)
1078 {
1079 exit_state = ES_HUP_PGRP;
1fd5e000 1080 /* Kill orphaned children on group leader exit */
f8f9b12e 1081 if (myself->has_pgid_children && myself->pid == myself->pgid)
1fd5e000 1082 {
985d0e68 1083 siginfo_t si = {0};
f6936c48
CF
1084 si.si_signo = -SIGHUP;
1085 si.si_code = SI_KERNEL;
1fd5e000
CF
1086 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1087 myself->pid, myself->pgid);
f6936c48 1088 kill_pgrp (myself->pgid, si);
1fd5e000 1089 }
3f5046a5 1090 }
1fd5e000 1091
3f5046a5
CF
1092 if (exit_state < ES_HUP_SID)
1093 {
1094 exit_state = ES_HUP_SID;
1fd5e000 1095 /* Kill the foreground process group on session leader exit */
b98ebf54 1096 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1fd5e000
CF
1097 {
1098 tty *tp = cygwin_shared->tty[myself->ctty];
1099 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1100 myself->pid, myself->sid);
1101
45a7e957 1102 /* CGF FIXME: This can't be right. */
1fd5e000 1103 if (tp->getsid () == myself->sid)
083abe54 1104 tp->kill_pgrp (SIGHUP);
1fd5e000 1105 }
ec300c99 1106
3f5046a5
CF
1107 }
1108
a611ae50
CF
1109 if (exit_state < ES_TITLE)
1110 {
1111 exit_state = ES_TITLE;
1112 /* restore console title */
1113 if (old_title && display_title)
1114 set_console_title (old_title);
1115 }
1116
3f5046a5
CF
1117 if (exit_state < ES_TTY_TERMINATE)
1118 {
1119 exit_state = ES_TTY_TERMINATE;
71d59a92 1120 cygwin_shared->tty.terminate ();
1fd5e000
CF
1121 }
1122
2380dfe1 1123 myself.exit (n);
1fd5e000
CF
1124}
1125
005c3065 1126extern "C" int
fc6a0dc8 1127cygwin_atexit (void (*fn) (void))
005c3065
CF
1128{
1129 int res;
fc6a0dc8
CF
1130 dll *d = dlls.find ((void *) _my_tls.retaddr ());
1131 res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
005c3065
CF
1132 return res;
1133}
1134
1135extern "C" void
1136cygwin_exit (int n)
1137{
c019a66c 1138 exit_state = ES_EXIT_STARTING;
005c3065
CF
1139 exit (n);
1140}
1141
1fd5e000
CF
1142extern "C" void
1143_exit (int n)
1144{
8cb359d9 1145 do_exit (((DWORD) n & 0xff) << 8);
1fd5e000
CF
1146}
1147
74434376
CF
1148extern "C" void cygwin_stackdump ();
1149
1fd5e000
CF
1150extern "C" void
1151__api_fatal (const char *fmt, ...)
1152{
1153 char buf[4096];
1154 va_list ap;
1155
1156 va_start (ap, fmt);
17f3068d 1157 int n = __small_sprintf (buf, "%P: *** fatal error - ");
2d1d1eb1 1158 __small_vsprintf (buf + n, fmt, ap);
1fd5e000 1159 va_end (ap);
a16b738d 1160 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1fd5e000 1161
1fd5e000 1162#ifdef DEBUGGING
0c55f6ed 1163 try_to_debug ();
1fd5e000 1164#endif
74434376 1165 cygwin_stackdump ();
84d38174 1166 myself.exit (__api_fatal_exit_val);
1fd5e000
CF
1167}
1168
d3fee5ec 1169void
77f4a250 1170multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
d3fee5ec 1171{
6d8bd861 1172 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
aaf219f0 1173 {
6d8bd861 1174 child_proc_info->type = _PROC_WHOOPS;
aaf219f0
CF
1175 return;
1176 }
5daa0835 1177
5ab0b5cf 1178 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
5daa0835
CF
1179 return;
1180
1181 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1182 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1183 else
2d76a612
CF
1184 api_fatal ("%s mismatch detected - %p/%p.\n\
1185This problem is probably due to using incompatible versions of the cygwin DLL.\n\
d3fee5ec 1186Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
77f4a250
CF
1187and delete all but the most recent version. The most recent version *should*\n\
1188reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
2d76a612
CF
1189installed the cygwin distribution. Rebooting is also suggested if you\n\
1190are unable to find another cygwin DLL.",
1191 what, magic_version, version);
d3fee5ec
CF
1192}
1193
166b2571
CF
1194#ifdef DEBUGGING
1195void __stdcall
1196cygbench (const char *s)
1197{
5ab0b5cf 1198 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
166b2571
CF
1199 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());
1200}
1201#endif
This page took 0.516173 seconds and 5 git commands to generate.