]> sourceware.org Git - newlib-cygwin.git/blob - winsup/cygwin/dcrt0.cc
* dcrt0.cc (__main): Force signal synchronization.
[newlib-cygwin.git] / winsup / cygwin / dcrt0.cc
1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
2
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
4 2007, 2008, 2009, 2010
5 Red Hat, Inc.
6
7 This file is part of Cygwin.
8
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
11 details. */
12
13 #include "winsup.h"
14 #include "miscfuncs.h"
15 #include <unistd.h>
16 #include <stdlib.h>
17 #include "glob.h"
18 #include <ctype.h>
19 #include <locale.h>
20 #include "environ.h"
21 #include "sigproc.h"
22 #include "pinfo.h"
23 #include "cygerrno.h"
24 #define NEED_VFORK
25 #include "perprocess.h"
26 #include "path.h"
27 #include "fhandler.h"
28 #include "dtable.h"
29 #include "cygheap.h"
30 #include "child_info_magic.h"
31 #include "cygtls.h"
32 #include "shared_info.h"
33 #include "cygwin_version.h"
34 #include "dll_init.h"
35 #include "heap.h"
36 #include "tls_pbuf.h"
37 #include "exception.h"
38 #include "cygxdr.h"
39 #include "ntdll.h"
40
41 #define MAX_AT_FILE_LEVEL 10
42
43 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
44
45 extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
46 extern "C" void __sinit (_reent *);
47
48 static int NO_COPY envc;
49 static char NO_COPY **envp;
50
51 static char title_buf[TITLESIZE + 1];
52
53 bool NO_COPY jit_debug;
54
55 static void
56 do_global_dtors ()
57 {
58 void (**pfunc) () = user_data->dtors;
59 if (pfunc)
60 {
61 user_data->dtors = NULL;
62 while (*++pfunc)
63 (*pfunc) ();
64 }
65 }
66
67 static void __stdcall
68 do_global_ctors (void (**in_pfunc)(), int force)
69 {
70 if (!force && in_forkee)
71 return; // inherit constructed stuff from parent pid
72
73 /* Run ctors backwards, so skip the first entry and find how many
74 there are, then run them. */
75
76 void (**pfunc) () = in_pfunc;
77
78 while (*++pfunc)
79 ;
80 while (--pfunc > in_pfunc)
81 (*pfunc) ();
82 }
83
84 /*
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.
89 */
90 static bool __stdcall
91 insert_file (char *name, char *&cmd)
92 {
93 HANDLE f;
94 DWORD size;
95 tmp_pathbuf tp;
96
97 PWCHAR wname = tp.w_get ();
98 sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
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 */
106
107 if (f == INVALID_HANDLE_VALUE)
108 {
109 debug_printf ("couldn't open file '%s', %E", name);
110 return false;
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);
120 return false;
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");
128 return false;
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");
139 return false;
140 }
141
142 tmp[size++] = ' ';
143 strcpy (tmp + size, cmd);
144 cmd = tmp;
145 return true;
146 }
147
148 static inline int
149 isquote (char c)
150 {
151 char ch = c;
152 return ch == '"' || ch == '\'';
153 }
154
155 /* Step over a run of characters delimited by quotes */
156 static /*__inline*/ char *
157 quoted (char *cmd, int winshell)
158 {
159 char *p;
160 char quote = *cmd;
161
162 if (!winshell)
163 {
164 char *p;
165 strcpy (cmd, cmd + 1);
166 if (*(p = strechr (cmd, quote)))
167 strcpy (p, p + 1);
168 return p;
169 }
170
171 const char *s = quote == '\'' ? "'" : "\\\"";
172 /* This must have been run from a Windows shell, so preserve
173 quotes for globify to play with later. */
174 while (*cmd && *++cmd)
175 if ((p = strpbrk (cmd, s)) == NULL)
176 {
177 cmd = strchr (cmd, '\0'); // no closing quote
178 break;
179 }
180 else if (*p == '\\')
181 cmd = ++p;
182 else if (quote == '"' && p[1] == '"')
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;
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. */
198 static int __stdcall
199 globify (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;
206 int dos_spec = isdrive (word);
207 if (!dos_spec && isquote (*word) && word[1] && word[2])
208 dos_spec = isdrive (word + 1);
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 {
231 if (dos_spec || *s != '\\')
232 /* nothing */;
233 else if (s[1] == quote || s[1] == '\\')
234 s++;
235 *p++ = '\\';
236 size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
237 if (cnt <= 1 || cnt == (size_t)-1)
238 *p++ = *s;
239 else
240 {
241 --s;
242 while (cnt-- > 0)
243 *p++ = *++s;
244 }
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 {
274 debug_printf ("argv[%d] = '%s'", n++, *gv);
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
285 static void __stdcall
286 build_argv (char *cmd, char **&argv, int &argc, int winshell)
287 {
288 int argvlen = 0;
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;
316 cmd = quoted (cmd, winshell && argc > 0);
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);
330 if (insert_file (word, cmd))
331 continue; // There's new stuff in cmd now
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 {
344 debug_printf ("argv[%d] = '%s'", argc, word);
345 argv[argc++] = word;
346 }
347 }
348
349 argv[argc] = NULL;
350
351 debug_printf ("argc %d", argc);
352 }
353
354 /* sanity and sync check */
355 void __stdcall
356 check_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)
362 api_fatal ("per_process sanity check failed");
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 */
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",
379 p->api_major, cygwin_version.api_major);
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;
386 }
387
388 child_info NO_COPY *child_proc_info = NULL;
389
390 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
391
392 void
393 child_info_fork::alloc_stack_hard_way (volatile char *b)
394 {
395 void *new_stack_pointer;
396 MEMORY_BASIC_INFORMATION m;
397 void *newbase;
398 int newlen;
399 bool guard;
400
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
406 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
407 {
408 newbase = curbot;
409 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
410 guard = false;
411 }
412 else
413 {
414 newbase = (LPBYTE) stacktop - (128 * 1024);
415 newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
416 guard = true;
417 }
418
419 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
420 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
421 stacktop, stackbottom);
422 new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
423 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
424 PAGE_EXECUTE_READWRITE))
425 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
426 new_stack_pointer, stacksize);
427 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
428 api_fatal ("fork: couldn't get new stack info, %E");
429
430 if (guard)
431 {
432 m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
433 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
434 CYGWIN_GUARD))
435 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
436 m.BaseAddress);
437 }
438 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
439 api_fatal ("fork: couldn't get new stack info, %E");
440 stacktop = m.BaseAddress;
441 b[0] = '\0';
442 }
443
444 void *getstack (void *) __attribute__ ((noinline));
445 volatile char *
446 getstack (volatile char * volatile p)
447 {
448 *p ^= 1;
449 *p ^= 1;
450 return p - 4096;
451 }
452
453 /* extend the stack prior to fork longjmp */
454
455 void
456 child_info_fork::alloc_stack ()
457 {
458 volatile char * volatile esp;
459 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
460 if (_tlsbase != stackbottom)
461 alloc_stack_hard_way (esp);
462 else
463 {
464 char *st = (char *) stacktop - 4096;
465 while (_tlstop >= st)
466 esp = getstack (esp);
467 stacksize = 0;
468 }
469 }
470
471 extern "C" void
472 break_here ()
473 {
474 static int NO_COPY sent_break;
475 if (!sent_break++)
476 DebugBreak ();
477 debug_printf ("break here");
478 }
479
480 static void
481 initial_env ()
482 {
483 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
484 _cygwin_testing = 1;
485
486 #ifdef DEBUGGING
487 char buf[NT_MAX_PATH];
488 DWORD len;
489
490 if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
491 {
492 DWORD ms = atoi (buf);
493 console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
494 Sleep (ms);
495 if (!strace.active () && !dynamically_loaded)
496 strace.hello ();
497 }
498 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
499 {
500 char buf1[NT_MAX_PATH];
501 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
502 strlwr (buf1);
503 strlwr (buf);
504 char *p = strpbrk (buf, ":=");
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);
512 jit_debug = true;
513 try_to_debug ();
514 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
515 break_here ();
516 }
517 }
518 #endif
519
520 }
521
522 child_info *
523 get_cygwin_startup_info ()
524 {
525 STARTUPINFO si;
526
527 GetStartupInfo (&si);
528 child_info *res = (child_info *) si.lpReserved2;
529
530 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
531 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
532 res = NULL;
533 else
534 {
535 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
536 multiple_cygwin_problem ("proc intro", res->intro, 0);
537 else if (res->cygheap != (void *) &_cygheap_start)
538 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
539 (DWORD) &_cygheap_start);
540
541 unsigned should_be_cb = 0;
542 switch (res->type)
543 {
544 case _PROC_FORK:
545 in_forkee = true;
546 should_be_cb = sizeof (child_info_fork);
547 /* fall through */;
548 case _PROC_SPAWN:
549 case _PROC_EXEC:
550 if (!should_be_cb)
551 should_be_cb = sizeof (child_info_spawn);
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));
556 if (res->isstraced ())
557 {
558 res->ready (false);
559 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
560 yield ();
561 strace.hello ();
562 }
563 break;
564 default:
565 system_printf ("unknown exec type %d", res->type);
566 /* intentionally fall through */
567 case _PROC_WHOOPS:
568 res = NULL;
569 break;
570 }
571 }
572
573 return res;
574 }
575
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
581 void
582 child_info_fork::handle_fork ()
583 {
584 cygheap_fixup_in_child (false);
585 memory_init (false);
586 myself.thisproc (NULL);
587 myself->uid = cygheap->user.real_uid;
588 myself->gid = cygheap->user.real_gid;
589
590 child_copy (parent, false,
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);
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
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. */
603 child_copy (parent, false,
604 "data", user_data->data_start, user_data->data_end,
605 "bss", user_data->bss_start, user_data->bss_end,
606 NULL);
607
608 if (fixup_mmaps_after_fork (parent))
609 api_fatal ("recreate_mmaps_after_fork_failed");
610 }
611
612 void
613 child_info_spawn::handle_spawn ()
614 {
615 extern void fixup_lockf_after_exec ();
616 HANDLE h;
617 cygheap_fixup_in_child (true);
618 memory_init (false);
619 if (!moreinfo->myself_pinfo ||
620 !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
621 GetCurrentProcess (), &h, 0,
622 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
623 h = NULL;
624 myself.thisproc (h);
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 ();
631 if (__stdin >= 0)
632 cygheap->fdtab.move_fd (__stdin, 0);
633 if (__stdout >= 0)
634 cygheap->fdtab.move_fd (__stdout, 1);
635 cygheap->user.groups.clear_supp ();
636
637 ready (true);
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
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 }
650 fixup_lockf_after_exec ();
651 }
652
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
657 static DEP_SYSTEM_POLICY_TYPE dep_system_policy = (DEP_SYSTEM_POLICY_TYPE) -1;
658
659 static void
660 disable_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;
672 if (!GetProcessDEPPolicy (GetCurrentProcess (), &ppolicy, &perm))
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 }
681 #endif
682
683 /* Retrieve and store system directory for later use. Note that the
684 directory is stored with a trailing backslash! */
685 static void
686 init_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
696 void __stdcall
697 dll_crt0_0 ()
698 {
699 init_windows_system_directory ();
700 init_global_security ();
701 initial_env ();
702
703 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
704
705 lock_process::init ();
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";
711 user_data->impure_ptr = _impure_ptr;
712 user_data->impure_ptr_ptr = &_impure_ptr;
713
714 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
715 GetCurrentProcess (), &hMainThread,
716 0, false, DUPLICATE_SAME_ACCESS);
717
718 OpenProcessToken (GetCurrentProcess (), MAXIMUM_ALLOWED, &hProcToken);
719 set_cygwin_privileges (hProcToken);
720
721 device::init ();
722 do_global_ctors (&__CTOR_LIST__, 1);
723 cygthread::init ();
724
725 child_proc_info = get_cygwin_startup_info ();
726 if (!child_proc_info)
727 memory_init (true);
728 else
729 {
730 cygwin_user_h = child_proc_info->user_h;
731 switch (child_proc_info->type)
732 {
733 case _PROC_FORK:
734 fork_info->handle_fork ();
735 break;
736 case _PROC_SPAWN:
737 case _PROC_EXEC:
738 spawn_info->handle_spawn ();
739 break;
740 }
741 }
742
743 user_data->threadinterface->Init ();
744
745 _cygtls::init ();
746
747 /* Initialize events */
748 events_init ();
749 tty_list::init_session ();
750
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. */
754
755 /* The disable_dep function disables DEP for all Cygwin processes if
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 ();
772 #endif
773
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. */
777 if (!wincap.has_buggy_thread_startup () && !dynamically_loaded)
778 sigproc_init ();
779
780 debug_printf ("finished dll_crt0_0 initialization");
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. */
787 void
788 dll_crt0_1 (void *)
789 {
790 extern void initial_setlocale ();
791
792 if (wincap.has_buggy_thread_startup () || dynamically_loaded)
793 sigproc_init ();
794 check_sanity_and_sync (user_data);
795
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 ();
801 user_shared->initialize ();
802
803 #ifdef CGF
804 int i = 0;
805 const int n = 2 * 1024 * 1024;
806 while (i--)
807 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
808 #endif
809
810 ProtectHandle (hMainThread);
811
812 cygheap->cwd.init ();
813
814 /* Initialize pthread mainthread when not forked and it is safe to call new,
815 otherwise it is reinitalized in fixup_after_fork */
816 if (!in_forkee)
817 {
818 pthread::init_mainthread ();
819 _pei386_runtime_relocator (user_data);
820 }
821
822 #ifdef DEBUGGING
823 strace.microseconds ();
824 #endif
825
826 create_signal_arrived (); /* FIXME: move into wait_sig? */
827
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
832 #ifdef NEWVFORK
833 cygheap->fdtab.vfork_child_fixup ();
834 main_vfork = vfork_storage.create ();
835 #endif
836
837 cygbench ("pre-forkee");
838 if (in_forkee)
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. */
847 if (fork_info->stacksize)
848 {
849 _tlsbase = (char *) fork_info->stackbottom;
850 _tlstop = (char *) fork_info->stacktop;
851 }
852
853 longjmp (fork_info->jmp, true);
854 }
855
856 __sinit (_impure_ptr);
857
858 #ifdef DEBUGGING
859 {
860 extern void fork_init ();
861 fork_init ();
862 }
863 #endif
864 pinfo_init (envp, envc);
865
866 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
867 old_title = title_buf;
868
869 /* Allocate cygheap->fdtab */
870 dtable_init ();
871
872 uinfo_init (); /* initialize user info */
873
874 /* Connect to tty. */
875 tty::init_session ();
876
877 /* Set internal locale to the environment settings. */
878 initial_setlocale ();
879
880 if (!__argc)
881 {
882 PWCHAR wline = GetCommandLineW ();
883 size_t size = sys_wcstombs (NULL, 0, wline);
884 char *line = (char *) alloca (size);
885 sys_wcstombs (line, size, wline);
886
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 {
896 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
897 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
898 new_argv0, NT_MAX_PATH);
899 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
900 }
901 }
902
903 __argc_safe = __argc;
904 if (user_data->premain[0])
905 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
906 user_data->premain[i] (__argc, __argv, user_data);
907
908 /* Set up standard fds in file descriptor table. */
909 cygheap->fdtab.stdio_init ();
910
911 /* Set up __progname for getopt error call. */
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;
919 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
920 *cp = '\0';
921 }
922
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
935 (void) xdr_set_vprintf (&cygxdr_vwarnx);
936 cygwin_finished_initializing = true;
937 /* Call init of loaded dlls. */
938 dlls.init ();
939
940 /* Execute any specified "premain" functions */
941 if (user_data->premain[PREMAIN_LEN / 2])
942 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
943 user_data->premain[i] (__argc, __argv, user_data);
944
945 set_errno (0);
946
947 if (dynamically_loaded)
948 return;
949
950 /* Disable case-insensitive globbing */
951 ignore_case_with_glob = false;
952
953 MALLOC_CHECK;
954 cygbench (__progname);
955
956 ld_preload ();
957 /* Per POSIX set the default application locale back to "C". */
958 _setlocale_r (_REENT, LC_CTYPE, "C");
959
960 if (user_data->main)
961 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
962 __asm__ (" \n\
963 .global __cygwin_exit_return \n\
964 __cygwin_exit_return: \n\
965 ");
966 }
967
968 extern "C" void __stdcall
969 _dll_crt0 ()
970 {
971 main_environ = user_data->envptr;
972 if (in_forkee)
973 fork_info->alloc_stack ();
974
975 _main_tls = &_my_tls;
976 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
977 }
978
979 void
980 dll_crt0 (per_process *uptr)
981 {
982 /* Set the local copy of the pointer into the user space. */
983 if (!in_forkee && uptr && uptr != user_data)
984 {
985 memcpy (user_data, uptr, per_process_overwrite);
986 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
987 }
988 _dll_crt0 ();
989 }
990
991 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
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.
996
997 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
998 from MSVC and non-cygwin MinGW applications. */
999 extern "C" void
1000 cygwin_dll_init ()
1001 {
1002 static char **envp;
1003 static int _fmode;
1004
1005 user_data->magic_biscuit = sizeof (per_process);
1006
1007 user_data->envptr = &envp;
1008 user_data->fmode_ptr = &_fmode;
1009
1010 _dll_crt0 ();
1011 }
1012
1013 extern "C" void
1014 __main (void)
1015 {
1016 /* Ordering is critical here. DLL ctors have already been
1017 run as they were being loaded, so we should stack the
1018 queued call to DLL dtors now. */
1019 atexit (dll_global_dtors);
1020 do_global_ctors (user_data->ctors, false);
1021 /* Now we have run global ctors, register their dtors.
1022
1023 At exit, global dtors will run first, so the app can still
1024 use shared library functions while terminating; then the
1025 DLLs will be destroyed; finally newlib will shut down stdio
1026 and terminate itself. */
1027 atexit (do_global_dtors);
1028 sig_dispatch_pending (true);
1029 }
1030
1031 void __stdcall
1032 do_exit (int status)
1033 {
1034 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1035
1036 #ifdef NEWVFORK
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 }
1043 #endif
1044
1045 lock_process until_exit (true);
1046
1047 if (exit_state < ES_EVENTS_TERMINATE)
1048 {
1049 exit_state = ES_EVENTS_TERMINATE;
1050 events_terminate ();
1051 }
1052
1053 UINT n = (UINT) status;
1054 if (exit_state < ES_THREADTERM)
1055 {
1056 exit_state = ES_THREADTERM;
1057 cygthread::terminate ();
1058 }
1059
1060 if (exit_state < ES_SIGNAL)
1061 {
1062 exit_state = ES_SIGNAL;
1063 signal (SIGCHLD, SIG_IGN);
1064 signal (SIGHUP, SIG_IGN);
1065 signal (SIGINT, SIG_IGN);
1066 signal (SIGQUIT, SIG_IGN);
1067 }
1068
1069 if (exit_state < ES_CLOSEALL)
1070 {
1071 exit_state = ES_CLOSEALL;
1072 close_all_files ();
1073 }
1074
1075 myself->stopsig = 0;
1076
1077 if (exit_state < ES_HUP_PGRP)
1078 {
1079 exit_state = ES_HUP_PGRP;
1080 /* Kill orphaned children on group leader exit */
1081 if (myself->has_pgid_children && myself->pid == myself->pgid)
1082 {
1083 siginfo_t si = {0};
1084 si.si_signo = -SIGHUP;
1085 si.si_code = SI_KERNEL;
1086 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1087 myself->pid, myself->pgid);
1088 kill_pgrp (myself->pgid, si);
1089 }
1090 }
1091
1092 if (exit_state < ES_HUP_SID)
1093 {
1094 exit_state = ES_HUP_SID;
1095 /* Kill the foreground process group on session leader exit */
1096 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
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
1102 /* CGF FIXME: This can't be right. */
1103 if (tp->getsid () == myself->sid)
1104 tp->kill_pgrp (SIGHUP);
1105 }
1106
1107 }
1108
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
1117 if (exit_state < ES_TTY_TERMINATE)
1118 {
1119 exit_state = ES_TTY_TERMINATE;
1120 cygwin_shared->tty.terminate ();
1121 }
1122
1123 myself.exit (n);
1124 }
1125
1126 extern "C" int
1127 cygwin_atexit (void (*fn) (void))
1128 {
1129 int res;
1130 dll *d = dlls.find ((void *) _my_tls.retaddr ());
1131 res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
1132 return res;
1133 }
1134
1135 extern "C" void
1136 cygwin_exit (int n)
1137 {
1138 exit_state = ES_EXIT_STARTING;
1139 exit (n);
1140 }
1141
1142 extern "C" void
1143 _exit (int n)
1144 {
1145 do_exit (((DWORD) n & 0xff) << 8);
1146 }
1147
1148 extern "C" void cygwin_stackdump ();
1149
1150 extern "C" void
1151 __api_fatal (const char *fmt, ...)
1152 {
1153 char buf[4096];
1154 va_list ap;
1155
1156 va_start (ap, fmt);
1157 int n = __small_sprintf (buf, "%P: *** fatal error - ");
1158 __small_vsprintf (buf + n, fmt, ap);
1159 va_end (ap);
1160 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1161
1162 #ifdef DEBUGGING
1163 try_to_debug ();
1164 #endif
1165 cygwin_stackdump ();
1166 myself.exit (__api_fatal_exit_val);
1167 }
1168
1169 void
1170 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1171 {
1172 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1173 {
1174 child_proc_info->type = _PROC_WHOOPS;
1175 return;
1176 }
1177
1178 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
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
1184 api_fatal ("%s mismatch detected - %p/%p.\n\
1185 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1186 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1187 and delete all but the most recent version. The most recent version *should*\n\
1188 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1189 installed the cygwin distribution. Rebooting is also suggested if you\n\
1190 are unable to find another cygwin DLL.",
1191 what, magic_version, version);
1192 }
1193
1194 #ifdef DEBUGGING
1195 void __stdcall
1196 cygbench (const char *s)
1197 {
1198 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1199 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());
1200 }
1201 #endif
This page took 0.087743 seconds and 5 git commands to generate.