1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
4 2007, 2008, 2009, 2010, 2011 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
13 #include "miscfuncs.h"
24 #include "perprocess.h"
29 #include "child_info_magic.h"
31 #include "shared_info.h"
32 #include "cygwin_version.h"
36 #include "exception.h"
42 #define MAX_AT_FILE_LEVEL 10
44 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
46 extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
47 extern "C" void __sinit (_reent *);
49 static int NO_COPY envc;
50 static char NO_COPY **envp;
52 bool NO_COPY jit_debug;
57 void (**pfunc) () = user_data->dtors;
60 user_data->dtors = NULL;
67 do_global_ctors (void (**in_pfunc)(), int force)
69 if (!force && in_forkee)
70 return; // inherit constructed stuff from parent pid
72 /* Run ctors backwards, so skip the first entry and find how many
73 there are, then run them. */
75 void (**pfunc) () = in_pfunc;
79 while (--pfunc > in_pfunc)
84 * Replaces @file in the command line with the contents of the file.
85 * There may be multiple @file's in a single command line
86 * A \@file is replaced with @file so that echo \@foo would print
87 * @foo and not the contents of foo.
90 insert_file (char *name, char *&cmd)
96 PWCHAR wname = tp.w_get ();
97 sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
98 f = CreateFileW (wname,
99 GENERIC_READ, /* open for reading */
100 FILE_SHARE_VALID_FLAGS, /* share for reading */
101 &sec_none_nih, /* default security */
102 OPEN_EXISTING, /* existing file only */
103 FILE_ATTRIBUTE_NORMAL, /* normal file */
104 NULL); /* no attr. template */
106 if (f == INVALID_HANDLE_VALUE)
108 debug_printf ("couldn't open file '%s', %E", name);
112 /* This only supports files up to about 4 billion bytes in
113 size. I am making the bold assumption that this is big
114 enough for this feature */
115 size = GetFileSize (f, NULL);
116 if (size == 0xFFFFFFFF)
118 debug_printf ("couldn't get file size for '%s', %E", name);
122 int new_size = strlen (cmd) + size + 2;
123 char *tmp = (char *) malloc (new_size);
126 debug_printf ("malloc failed, %E");
130 /* realloc passed as it should */
133 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
135 if (!rf_result || (rf_read != size))
137 debug_printf ("ReadFile failed, %E");
142 strcpy (tmp + size, cmd);
151 return ch == '"' || ch == '\'';
154 /* Step over a run of characters delimited by quotes */
155 static /*__inline*/ char *
156 quoted (char *cmd, int winshell)
164 strcpy (cmd, cmd + 1);
165 if (*(p = strechr (cmd, quote)))
170 const char *s = quote == '\'' ? "'" : "\\\"";
171 /* This must have been run from a Windows shell, so preserve
172 quotes for globify to play with later. */
173 while (*cmd && *++cmd)
174 if ((p = strpbrk (cmd, s)) == NULL)
176 cmd = strchr (cmd, '\0'); // no closing quote
181 else if (quote == '"' && p[1] == '"')
184 cmd = ++p; // a quoted quote
188 cmd = p + 1; // point to after end
194 /* Perform a glob on word if it contains wildcard characters.
195 Also quote every character between quotes to force glob to
196 treat the characters literally. */
198 globify (char *word, char **&argv, int &argc, int &argvlen)
200 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
205 int dos_spec = isdrive (word);
206 if (!dos_spec && isquote (*word) && word[1] && word[2])
207 dos_spec = isdrive (word + 1);
209 /* We'll need more space if there are quoting characters in
210 word. If that is the case, doubling the size of the
211 string should provide more than enough space. */
212 if (strpbrk (word, "'\""))
214 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
216 /* Fill pattern with characters from word, quoting any
217 characters found within quotes. */
218 for (p = pattern, s = word; *s != '\000'; s++, p++)
221 if (dos_spec && *s == '\\')
228 while (*++s && *s != quote)
230 if (dos_spec || *s != '\\')
232 else if (s[1] == quote || s[1] == '\\')
235 size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
236 if (cnt <= 1 || cnt == (size_t)-1)
256 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
257 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
260 /* Allocate enough space in argv for the matched filenames. */
262 if ((argc += gl.gl_pathc) > argvlen)
265 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
268 /* Copy the matched filenames to argv. */
269 char **gv = gl.gl_pathv;
270 char **av = argv + n;
273 debug_printf ("argv[%d] = '%s'", n++, *gv);
277 /* Clean up after glob. */
282 /* Build argv, argc from string passed from Windows. */
284 static void __stdcall
285 build_argv (char *cmd, char **&argv, int &argc, int winshell)
288 int nesting = 0; // monitor "nesting" from insert_file
294 /* Scan command line until there is nothing left. */
304 /* Found the beginning of an argument. */
306 char *sawquote = NULL;
309 if (*cmd != '"' && (!winshell || *cmd != '\''))
310 cmd++; // Skip over this character
312 /* Skip over characters until the closing quote */
315 cmd = quoted (cmd, winshell && argc > 0);
317 if (issep (*cmd)) // End of argument if space
321 *cmd++ = '\0'; // Terminate `word'
323 /* Possibly look for @file construction assuming that this isn't
324 the very first argument and the @ wasn't quoted */
325 if (argc && sawquote != word && *word == '@')
327 if (++nesting > MAX_AT_FILE_LEVEL)
328 api_fatal ("Too many levels of nesting for %s", word);
329 if (insert_file (word, cmd))
330 continue; // There's new stuff in cmd now
333 /* See if we need to allocate more space for argv */
337 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
340 /* Add word to argv file after (optional) wildcard expansion. */
341 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
343 debug_printf ("argv[%d] = '%s'", argc, word);
350 debug_printf ("argc %d", argc);
353 /* sanity and sync check */
355 check_sanity_and_sync (per_process *p)
357 /* Sanity check to make sure developers didn't change the per_process */
358 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
359 /* about changing it]. */
360 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
361 api_fatal ("per_process sanity check failed");
363 /* Make sure that the app and the dll are in sync. */
365 /* Complain if older than last incompatible change */
366 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
367 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
368 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
370 /* magic_biscuit != 0 if using the old style version numbering scheme. */
371 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
372 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
373 p->magic_biscuit, SIZEOF_PER_PROCESS);
375 /* Complain if incompatible API changes made */
376 if (p->api_major > cygwin_version.api_major)
377 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
378 p->api_major, cygwin_version.api_major);
380 /* This is a kludge to work around a version of _cygwin_common_crt0
381 which overwrote the cxx_malloc field with the local DLL copy.
382 Hilarity ensues if the DLL is not loaded while the process
384 __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
387 child_info NO_COPY *child_proc_info = NULL;
389 #define CYGWIN_GUARD (PAGE_READWRITE | PAGE_GUARD)
392 child_info_fork::alloc_stack_hard_way (volatile char *b)
397 /* First check if the requested stack area is part of the user heap
398 or part of a mmapped region. If so, we have been started from a
399 pthread with an application-provided stack, and the stack has just
401 if ((stacktop >= cygheap->user_heap.base
402 && stackbottom <= cygheap->user_heap.max)
403 || is_mmapped_region ((caddr_t) stacktop, (caddr_t) stackbottom))
406 /* First, try to reserve the entire stack. */
407 stacksize = (char *) stackbottom - (char *) stackaddr;
408 if (!VirtualAlloc (stackaddr, stacksize, MEM_RESERVE, PAGE_NOACCESS))
409 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
410 stackaddr, stackbottom);
411 stacksize = (char *) stackbottom - (char *) stacktop;
412 stack_ptr = VirtualAlloc (stacktop, stacksize, MEM_COMMIT, PAGE_READWRITE);
414 abort ("can't commit memory for stack %p(%d), %E", stacktop, stacksize);
415 if (guardsize != (size_t) -1)
417 /* Allocate PAGE_GUARD page if it still fits. */
418 if (stack_ptr > stackaddr)
420 stack_ptr = (void *) ((LPBYTE) stack_ptr
421 - wincap.page_size ());
422 if (!VirtualAlloc (stack_ptr, wincap.page_size (), MEM_COMMIT,
424 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
427 /* Allocate POSIX guard pages. */
429 VirtualAlloc (stackaddr, guardsize, MEM_COMMIT, PAGE_NOACCESS);
434 void *getstack (void *) __attribute__ ((noinline));
436 getstack (volatile char * volatile p)
443 /* extend the stack prior to fork longjmp */
446 child_info_fork::alloc_stack ()
448 volatile char * volatile esp;
449 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
450 /* Make sure not to try a hard allocation if we have been forked off from
451 the main thread of a Cygwin process which has been started from a 64 bit
452 parent. In that case the _tlsbase of the forked child is not the same
453 as the _tlsbase of the parent (== stackbottom), but only because the
454 stack of the parent has been slightly rearranged. See comment in
455 wow64_revert_to_original_stack for details. We check here if the
456 parent stack fits into the child stack. */
457 if (_tlsbase != stackbottom
458 && (!wincap.is_wow64 ()
459 || stacktop < (char *) NtCurrentTeb ()->DeallocationStack
460 || stackbottom > _tlsbase))
461 alloc_stack_hard_way (esp);
464 char *st = (char *) stacktop - 4096;
465 while (_tlstop >= st)
466 esp = getstack (esp);
468 /* This only affects forked children of a process started from a native
469 64 bit process, but it doesn't hurt to do it unconditionally. Fix
470 StackBase in the child to be the same as in the parent, so that the
471 computation of _my_tls is correct. */
472 _tlsbase = (char *) stackbottom;
479 static int NO_COPY sent_break;
482 debug_printf ("break here");
488 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
493 char buf[NT_MAX_PATH];
494 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
496 char buf1[NT_MAX_PATH];
497 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
500 char *p = strpbrk (buf, ":=");
502 p = (char *) "gdb.exe -nw";
505 if (strstr (buf1, buf))
507 error_start_init (p);
510 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
518 get_cygwin_startup_info ()
522 GetStartupInfo (&si);
523 child_info *res = (child_info *) si.lpReserved2;
525 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
526 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
528 strace.activate (false);
533 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
534 multiple_cygwin_problem ("proc intro", res->intro, 0);
535 else if (res->cygheap != (void *) &_cygheap_start)
536 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
537 (DWORD) &_cygheap_start);
539 unsigned should_be_cb = 0;
544 should_be_cb = sizeof (child_info_fork);
549 should_be_cb = sizeof (child_info_spawn);
550 if (should_be_cb != res->cb)
551 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
552 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
553 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
554 if (res->isstraced ())
556 while (!being_debugged ())
558 strace.activate (res->type == _CH_FORK);
562 system_printf ("unknown exec type %d", res->type);
563 /* intentionally fall through */
573 #define dll_data_start &_data_start__
574 #define dll_data_end &_data_end__
575 #define dll_bss_start &_bss_start__
576 #define dll_bss_end &_bss_end__
579 child_info_fork::handle_fork ()
581 cygheap_fixup_in_child (false);
583 myself.thisproc (NULL);
584 myself->uid = cygheap->user.real_uid;
585 myself->gid = cygheap->user.real_gid;
587 child_copy (parent, false,
588 "dll data", dll_data_start, dll_data_end,
589 "dll bss", dll_bss_start, dll_bss_end,
590 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
593 /* Do the relocations here. These will actually likely be overwritten by the
594 below child_copy but we do them here in case there is a read-only section
595 which does not get copied by fork. */
596 _pei386_runtime_relocator (user_data);
598 /* step 2 now that the dll has its heap filled in, we can fill in the
599 user's data and bss since user_data is now filled out. */
600 child_copy (parent, false,
601 "data", user_data->data_start, user_data->data_end,
602 "bss", user_data->bss_start, user_data->bss_end,
605 if (fixup_mmaps_after_fork (parent))
606 api_fatal ("recreate_mmaps_after_fork_failed");
610 child_info_spawn::handle_spawn ()
612 extern void fixup_lockf_after_exec ();
614 cygheap_fixup_in_child (true);
616 if (!moreinfo->myself_pinfo ||
617 !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
618 GetCurrentProcess (), &h, 0,
619 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
622 __argc = moreinfo->argc;
623 __argv = moreinfo->argv;
624 envp = moreinfo->envp;
625 envc = moreinfo->envc;
626 if (!dynamically_loaded)
627 cygheap->fdtab.fixup_after_exec ();
629 cygheap->fdtab.move_fd (__stdin, 0);
631 cygheap->fdtab.move_fd (__stdout, 1);
632 cygheap->user.groups.clear_supp ();
634 /* If we're execing we may have "inherited" a list of children forked by the
635 previous process executing under this pid. Reattach them here so that we
636 can wait for them. */
637 if (type == _CH_EXEC)
638 reattach_children ();
642 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
643 handles might get confused. */
644 CloseHandle (child_proc_info->parent);
645 child_proc_info->parent = NULL;
647 signal_fixup_after_exec ();
648 fixup_lockf_after_exec ();
651 /* Retrieve and store system directory for later use. Note that the
652 directory is stored with a trailing backslash! */
654 init_windows_system_directory ()
656 if (!windows_system_directory_length)
658 windows_system_directory_length =
659 GetSystemDirectoryW (windows_system_directory, MAX_PATH);
660 if (windows_system_directory_length == 0)
661 api_fatal ("can't find windows system directory");
662 windows_system_directory[windows_system_directory_length++] = L'\\';
663 windows_system_directory[windows_system_directory_length] = L'\0';
665 system_wow64_directory_length =
666 GetSystemWow64DirectoryW (system_wow64_directory, MAX_PATH);
667 if (system_wow64_directory_length)
669 system_wow64_directory[system_wow64_directory_length++] = L'\\';
670 system_wow64_directory[system_wow64_directory_length] = L'\0';
678 child_proc_info = get_cygwin_startup_info ();
679 init_windows_system_directory ();
680 init_global_security ();
683 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
685 lock_process::init ();
686 _impure_ptr = _GLOBAL_REENT;
687 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
688 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
689 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
690 _impure_ptr->_current_locale = "C";
691 user_data->impure_ptr = _impure_ptr;
692 user_data->impure_ptr_ptr = &_impure_ptr;
694 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
695 GetCurrentProcess (), &hMainThread,
696 0, false, DUPLICATE_SAME_ACCESS);
698 NtOpenProcessToken (NtCurrentProcess (), MAXIMUM_ALLOWED, &hProcToken);
699 set_cygwin_privileges (hProcToken);
702 do_global_ctors (&__CTOR_LIST__, 1);
705 if (!child_proc_info)
708 /* WOW64 process? Check if we have been started from 64 bit process
709 and if our stack is at an unusual address. Set wow64_has_64bit_parent
710 if so. Problem description in wow64_test_for_64bit_parent. */
711 if (wincap.is_wow64 ())
712 wow64_has_64bit_parent = wow64_test_for_64bit_parent ();
716 cygwin_user_h = child_proc_info->user_h;
717 switch (child_proc_info->type)
720 fork_info->handle_fork ();
724 spawn_info->handle_spawn ();
729 user_data->threadinterface->Init ();
733 /* Initialize events */
735 tty_list::init_session ();
737 _main_tls = &_my_tls;
739 /* Initialize signal processing here, early, in the hopes that the creation
740 of a thread early in the process will cause more predictability in memory
741 layout for the main thread. */
742 if (!dynamically_loaded)
745 debug_printf ("finished dll_crt0_0 initialization");
748 /* Take over from libc's crt0.o and start the application. Note the
749 various special cases when Cygwin DLL is being runtime loaded (as
750 opposed to being link-time loaded by Cygwin apps) from a non
751 cygwin app via LoadLibrary. */
755 extern void initial_setlocale ();
757 if (dynamically_loaded)
760 check_sanity_and_sync (user_data);
762 /* Initialize malloc and then call user_shared_initialize since it relies
763 on a functioning malloc and it's possible that the user's program may
764 have overridden malloc. We only know about that at this stage,
767 user_shared->initialize ();
771 const int n = 2 * 1024 * 1024;
774 void *p = cmalloc (HEAP_STR, n);
776 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
779 small_printf ("total allocated %p\n", (i - 1) * n);
785 ProtectHandle (hMainThread);
787 cygheap->cwd.init ();
789 /* Initialize pthread mainthread when not forked and it is safe to call new,
790 otherwise it is reinitalized in fixup_after_fork */
793 pthread::init_mainthread ();
794 _pei386_runtime_relocator (user_data);
798 strace.microseconds ();
801 create_signal_arrived (); /* FIXME: move into wait_sig? */
803 /* Initialize debug muto, if DLL is built with --enable-debugging.
804 Need to do this before any helper threads start. */
808 cygheap->fdtab.vfork_child_fixup ();
809 main_vfork = vfork_storage.create ();
812 cygbench ("pre-forkee");
815 /* If we've played with the stack, stacksize != 0. That means that
816 fork() was invoked from other than the main thread. Make sure that
817 frame pointer is referencing the new stack so that the OS knows what
818 to do when it needs to increase the size of the stack.
820 NOTE: Don't do anything that involves the stack until you've completed
822 if (fork_info->stackaddr)
824 _tlsbase = (char *) fork_info->stackbottom;
825 _tlstop = (char *) fork_info->stacktop;
828 longjmp (fork_info->jmp, true);
831 __sinit (_impure_ptr);
835 extern void fork_init ();
839 pinfo_init (envp, envc);
842 /* Allocate cygheap->fdtab */
845 uinfo_init (); /* initialize user info */
847 /* Connect to tty. */
848 tty::init_session ();
850 /* Set internal locale to the environment settings. */
851 initial_setlocale ();
855 PWCHAR wline = GetCommandLineW ();
856 size_t size = sys_wcstombs (NULL, 0, wline);
857 char *line = (char *) alloca (size);
858 sys_wcstombs (line, size, wline);
860 /* Scan the command line and build argv. Expand wildcards if not
861 called from another cygwin process. */
862 build_argv (line, __argv, __argc,
863 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
865 /* Convert argv[0] to posix rules if it's currently blatantly
867 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
869 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
870 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
871 new_argv0, NT_MAX_PATH);
872 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
876 __argc_safe = __argc;
877 if (user_data->premain[0])
878 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
879 user_data->premain[i] (__argc, __argv, user_data);
881 /* Set up standard fds in file descriptor table. */
882 cygheap->fdtab.stdio_init ();
884 /* Set up __progname for getopt error call. */
885 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
888 __progname = __argv[0];
889 program_invocation_name = __argv[0];
890 program_invocation_short_name = __progname;
893 char *cp = strchr (__progname, '\0') - 4;
894 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
898 (void) xdr_set_vprintf (&cygxdr_vwarnx);
899 cygwin_finished_initializing = true;
900 /* Call init of loaded dlls. */
903 /* Execute any specified "premain" functions */
904 if (user_data->premain[PREMAIN_LEN / 2])
905 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
906 user_data->premain[i] (__argc, __argv, user_data);
910 if (dynamically_loaded)
912 _setlocale_r (_REENT, LC_CTYPE, "C");
916 /* Disable case-insensitive globbing */
917 ignore_case_with_glob = false;
920 cygbench (__progname);
923 /* Per POSIX set the default application locale back to "C". */
924 _setlocale_r (_REENT, LC_CTYPE, "C");
928 /* Create a copy of Cygwin's version of __argv so that, if the user makes
929 a change to an element of argv[] it does not affect Cygwin's argv.
930 Changing the the contents of what argv[n] points to will still
931 affect Cygwin. This is similar (but not exactly like) Linux. */
932 char *newargv[__argc + 1];
933 char **nav = newargv;
935 while ((*nav++ = *oav++) != NULL)
937 cygwin_exit (user_data->main (__argc, newargv, *user_data->envptr));
940 .global __cygwin_exit_return \n\
941 __cygwin_exit_return: \n\
945 extern "C" void __stdcall
948 /* Handle WOW64 process started from native 64 bit process. See comment
949 in wow64_test_for_64bit_parent for a full problem description. */
950 if (wow64_has_64bit_parent && !dynamically_loaded)
952 /* Must be static since it's referenced after the stack pointers have
954 static PVOID allocationbase = 0;
956 /* Check if we just move the stack. See comment in
957 wow64_revert_to_original_stack for the gory details. */
958 PVOID stackaddr = wow64_revert_to_original_stack (allocationbase);
961 /* 2nd half of the stack move. First set stack pointers to
964 movl %[ADDR], %%esp \n\
965 movl %%esp, %%ebp \n"
966 : : [ADDR] "r" (stackaddr));
967 /* Now we're back on the original stack. Free up space taken by the
968 former main thread stack and... */
969 VirtualFree (NtCurrentTeb ()->DeallocationStack,
971 /* ...set DeallocationStack correctly. */
972 NtCurrentTeb ()->DeallocationStack = allocationbase;
975 /* Fall back to respawn if wow64_revert_to_original_stack fails. */
976 wow64_respawn_process ();
981 main_environ = user_data->envptr;
984 fork_info->alloc_stack ();
985 _main_tls = &_my_tls;
988 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
992 dll_crt0 (per_process *uptr)
994 /* Set the local copy of the pointer into the user space. */
995 if (!in_forkee && uptr && uptr != user_data)
997 memcpy (user_data, uptr, per_process_overwrite);
998 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
1003 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
1004 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
1005 calling this function, and that storage must not be overwritten until you
1006 unload cygwin1.dll, as it is used for _my_tls. It is best to load
1007 cygwin1.dll before spawning any additional threads in your process.
1009 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
1010 from MSVC and non-cygwin MinGW applications. */
1017 user_data->magic_biscuit = sizeof (per_process);
1019 user_data->envptr = &envp;
1020 user_data->fmode_ptr = &_fmode;
1028 /* Ordering is critical here. DLL ctors have already been
1029 run as they were being loaded, so we should stack the
1030 queued call to DLL dtors now. */
1031 atexit (dll_global_dtors);
1032 do_global_ctors (user_data->ctors, false);
1033 /* Now we have run global ctors, register their dtors.
1035 At exit, global dtors will run first, so the app can still
1036 use shared library functions while terminating; then the
1037 DLLs will be destroyed; finally newlib will shut down stdio
1038 and terminate itself. */
1039 atexit (do_global_dtors);
1040 sig_dispatch_pending (true);
1044 do_exit (int status)
1046 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1049 vfork_save *vf = vfork_storage.val ();
1050 if (vf != NULL && vf->pid < 0)
1052 exit_state = ES_NOT_EXITING;
1053 vf->restore_exit (status);
1057 lock_process until_exit (true);
1059 if (exit_state < ES_EVENTS_TERMINATE)
1061 exit_state = ES_EVENTS_TERMINATE;
1062 events_terminate ();
1065 if (exit_state < ES_SIGNAL)
1067 exit_state = ES_SIGNAL;
1068 signal (SIGCHLD, SIG_IGN);
1069 signal (SIGHUP, SIG_IGN);
1070 signal (SIGINT, SIG_IGN);
1071 signal (SIGQUIT, SIG_IGN);
1074 if (exit_state < ES_CLOSEALL)
1076 exit_state = ES_CLOSEALL;
1080 UINT n = (UINT) status;
1081 if (exit_state < ES_THREADTERM)
1083 exit_state = ES_THREADTERM;
1084 cygthread::terminate ();
1087 myself->stopsig = 0;
1089 if (exit_state < ES_HUP_PGRP)
1091 exit_state = ES_HUP_PGRP;
1092 /* Kill orphaned children on group leader exit */
1093 if (myself->has_pgid_children && myself->pid == myself->pgid)
1096 si.si_signo = -SIGHUP;
1097 si.si_code = SI_KERNEL;
1098 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1099 myself->pid, myself->pgid);
1100 kill_pgrp (myself->pgid, si);
1104 if (exit_state < ES_HUP_SID)
1106 exit_state = ES_HUP_SID;
1107 /* Kill the foreground process group on session leader exit */
1108 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1110 tty *tp = cygwin_shared->tty[myself->ctty];
1111 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1112 myself->pid, myself->sid);
1114 /* CGF FIXME: This can't be right. */
1115 if (tp->getsid () == myself->sid)
1116 tp->kill_pgrp (SIGHUP);
1125 cygwin_atexit (void (*fn) (void))
1128 dll *d = dlls.find ((void *) _my_tls.retaddr ());
1129 res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
1136 exit_state = ES_EXIT_STARTING;
1143 do_exit (((DWORD) n & 0xff) << 8);
1146 extern "C" void cygwin_stackdump ();
1149 vapi_fatal (const char *fmt, va_list ap)
1152 int n = __small_sprintf (buf, "%P: *** fatal error %s- ", in_forkee ? "in forked process " : "");
1153 __small_vsprintf (buf + n, fmt, ap);
1155 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1160 cygwin_stackdump ();
1161 myself.exit (__api_fatal_exit_val);
1165 api_fatal (const char *fmt, ...)
1170 vapi_fatal (fmt, ap);
1174 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1176 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1178 child_proc_info->type = _CH_WHOOPS;
1182 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1185 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1186 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1188 api_fatal ("%s mismatch detected - %p/%p.\n\
1189 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1190 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1191 and delete all but the most recent version. The most recent version *should*\n\
1192 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1193 installed the cygwin distribution. Rebooting is also suggested if you\n\
1194 are unable to find another cygwin DLL.",
1195 what, magic_version, version);
1200 cygbench (const char *s)
1202 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1203 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());