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 on XP/64 or Server 2003/64? Check if we have been
709 started from 64 bit process and if our stack is at an unusual
710 address. Set wow64_needs_stack_adjustment if so. Problem
711 description in wow64_test_for_64bit_parent. */
712 if (wincap.wow64_has_secondary_stack ())
713 wow64_needs_stack_adjustment = wow64_test_for_64bit_parent ();
717 cygwin_user_h = child_proc_info->user_h;
718 switch (child_proc_info->type)
721 fork_info->handle_fork ();
725 spawn_info->handle_spawn ();
730 user_data->threadinterface->Init ();
734 /* Initialize events */
736 tty_list::init_session ();
738 _main_tls = &_my_tls;
740 /* Initialize signal processing here, early, in the hopes that the creation
741 of a thread early in the process will cause more predictability in memory
742 layout for the main thread. */
743 if (!dynamically_loaded)
746 debug_printf ("finished dll_crt0_0 initialization");
749 /* Take over from libc's crt0.o and start the application. Note the
750 various special cases when Cygwin DLL is being runtime loaded (as
751 opposed to being link-time loaded by Cygwin apps) from a non
752 cygwin app via LoadLibrary. */
756 extern void initial_setlocale ();
758 if (dynamically_loaded)
761 check_sanity_and_sync (user_data);
763 /* Initialize malloc and then call user_shared_initialize since it relies
764 on a functioning malloc and it's possible that the user's program may
765 have overridden malloc. We only know about that at this stage,
768 user_shared->initialize ();
772 const int n = 2 * 1024 * 1024;
775 void *p = cmalloc (HEAP_STR, n);
777 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
780 small_printf ("total allocated %p\n", (i - 1) * n);
786 ProtectHandle (hMainThread);
788 cygheap->cwd.init ();
790 /* Initialize pthread mainthread when not forked and it is safe to call new,
791 otherwise it is reinitalized in fixup_after_fork */
794 pthread::init_mainthread ();
795 _pei386_runtime_relocator (user_data);
799 strace.microseconds ();
802 create_signal_arrived (); /* FIXME: move into wait_sig? */
804 /* Initialize debug muto, if DLL is built with --enable-debugging.
805 Need to do this before any helper threads start. */
809 cygheap->fdtab.vfork_child_fixup ();
810 main_vfork = vfork_storage.create ();
813 cygbench ("pre-forkee");
816 /* If we've played with the stack, stacksize != 0. That means that
817 fork() was invoked from other than the main thread. Make sure that
818 frame pointer is referencing the new stack so that the OS knows what
819 to do when it needs to increase the size of the stack.
821 NOTE: Don't do anything that involves the stack until you've completed
823 if (fork_info->stackaddr)
825 _tlsbase = (char *) fork_info->stackbottom;
826 _tlstop = (char *) fork_info->stacktop;
829 longjmp (fork_info->jmp, true);
832 __sinit (_impure_ptr);
836 extern void fork_init ();
840 pinfo_init (envp, envc);
843 /* Allocate cygheap->fdtab */
846 uinfo_init (); /* initialize user info */
848 /* Connect to tty. */
849 tty::init_session ();
851 /* Set internal locale to the environment settings. */
852 initial_setlocale ();
856 PWCHAR wline = GetCommandLineW ();
857 size_t size = sys_wcstombs (NULL, 0, wline);
858 char *line = (char *) alloca (size);
859 sys_wcstombs (line, size, wline);
861 /* Scan the command line and build argv. Expand wildcards if not
862 called from another cygwin process. */
863 build_argv (line, __argv, __argc,
864 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
866 /* Convert argv[0] to posix rules if it's currently blatantly
868 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
870 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
871 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
872 new_argv0, NT_MAX_PATH);
873 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
877 __argc_safe = __argc;
878 if (user_data->premain[0])
879 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
880 user_data->premain[i] (__argc, __argv, user_data);
882 /* Set up standard fds in file descriptor table. */
883 cygheap->fdtab.stdio_init ();
885 /* Set up __progname for getopt error call. */
886 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
889 __progname = __argv[0];
890 program_invocation_name = __argv[0];
891 program_invocation_short_name = __progname;
894 char *cp = strchr (__progname, '\0') - 4;
895 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
899 (void) xdr_set_vprintf (&cygxdr_vwarnx);
900 cygwin_finished_initializing = true;
901 /* Call init of loaded dlls. */
904 /* Execute any specified "premain" functions */
905 if (user_data->premain[PREMAIN_LEN / 2])
906 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
907 user_data->premain[i] (__argc, __argv, user_data);
911 if (dynamically_loaded)
913 _setlocale_r (_REENT, LC_CTYPE, "C");
917 /* Disable case-insensitive globbing */
918 ignore_case_with_glob = false;
921 cygbench (__progname);
924 /* Per POSIX set the default application locale back to "C". */
925 _setlocale_r (_REENT, LC_CTYPE, "C");
929 /* Create a copy of Cygwin's version of __argv so that, if the user makes
930 a change to an element of argv[] it does not affect Cygwin's argv.
931 Changing the the contents of what argv[n] points to will still
932 affect Cygwin. This is similar (but not exactly like) Linux. */
933 char *newargv[__argc + 1];
934 char **nav = newargv;
936 while ((*nav++ = *oav++) != NULL)
938 cygwin_exit (user_data->main (__argc, newargv, *user_data->envptr));
941 .global __cygwin_exit_return \n\
942 __cygwin_exit_return: \n\
946 extern "C" void __stdcall
949 /* Handle WOW64 process on XP/2K3 which has been started from native 64 bit
950 process. See comment in wow64_test_for_64bit_parent for a full problem
952 if (wow64_needs_stack_adjustment && !dynamically_loaded)
954 /* Must be static since it's referenced after the stack pointers have
956 static PVOID allocationbase = 0;
958 /* Check if we just move the stack. See comment in
959 wow64_revert_to_original_stack for the gory details. */
960 PVOID stackaddr = wow64_revert_to_original_stack (allocationbase);
963 /* 2nd half of the stack move. Set stack pointers to new address. */
965 movl %[ADDR], %%esp \n\
966 movl %%esp, %%ebp \n"
967 : : [ADDR] "r" (stackaddr));
968 /* Now we're back on the original stack. Free up space taken by the
969 former main thread stack and set DeallocationStack correctly. */
970 VirtualFree (NtCurrentTeb ()->DeallocationStack, 0, MEM_RELEASE);
971 NtCurrentTeb ()->DeallocationStack = allocationbase;
974 /* Fall back to respawn if wow64_revert_to_original_stack fails. */
975 wow64_respawn_process ();
980 main_environ = user_data->envptr;
983 fork_info->alloc_stack ();
984 _main_tls = &_my_tls;
987 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
991 dll_crt0 (per_process *uptr)
993 /* Set the local copy of the pointer into the user space. */
994 if (!in_forkee && uptr && uptr != user_data)
996 memcpy (user_data, uptr, per_process_overwrite);
997 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
1002 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
1003 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
1004 calling this function, and that storage must not be overwritten until you
1005 unload cygwin1.dll, as it is used for _my_tls. It is best to load
1006 cygwin1.dll before spawning any additional threads in your process.
1008 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
1009 from MSVC and non-cygwin MinGW applications. */
1016 user_data->magic_biscuit = sizeof (per_process);
1018 user_data->envptr = &envp;
1019 user_data->fmode_ptr = &_fmode;
1027 /* Ordering is critical here. DLL ctors have already been
1028 run as they were being loaded, so we should stack the
1029 queued call to DLL dtors now. */
1030 atexit (dll_global_dtors);
1031 do_global_ctors (user_data->ctors, false);
1032 /* Now we have run global ctors, register their dtors.
1034 At exit, global dtors will run first, so the app can still
1035 use shared library functions while terminating; then the
1036 DLLs will be destroyed; finally newlib will shut down stdio
1037 and terminate itself. */
1038 atexit (do_global_dtors);
1039 sig_dispatch_pending (true);
1043 do_exit (int status)
1045 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1048 vfork_save *vf = vfork_storage.val ();
1049 if (vf != NULL && vf->pid < 0)
1051 exit_state = ES_NOT_EXITING;
1052 vf->restore_exit (status);
1056 lock_process until_exit (true);
1058 if (exit_state < ES_EVENTS_TERMINATE)
1060 exit_state = ES_EVENTS_TERMINATE;
1061 events_terminate ();
1064 if (exit_state < ES_SIGNAL)
1066 exit_state = ES_SIGNAL;
1067 signal (SIGCHLD, SIG_IGN);
1068 signal (SIGHUP, SIG_IGN);
1069 signal (SIGINT, SIG_IGN);
1070 signal (SIGQUIT, SIG_IGN);
1073 if (exit_state < ES_CLOSEALL)
1075 exit_state = ES_CLOSEALL;
1079 UINT n = (UINT) status;
1080 if (exit_state < ES_THREADTERM)
1082 exit_state = ES_THREADTERM;
1083 cygthread::terminate ();
1086 myself->stopsig = 0;
1088 if (exit_state < ES_HUP_PGRP)
1090 exit_state = ES_HUP_PGRP;
1091 /* Kill orphaned children on group leader exit */
1092 if (myself->has_pgid_children && myself->pid == myself->pgid)
1095 si.si_signo = -SIGHUP;
1096 si.si_code = SI_KERNEL;
1097 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1098 myself->pid, myself->pgid);
1099 kill_pgrp (myself->pgid, si);
1103 if (exit_state < ES_HUP_SID)
1105 exit_state = ES_HUP_SID;
1106 /* Kill the foreground process group on session leader exit */
1107 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1109 tty *tp = cygwin_shared->tty[myself->ctty];
1110 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1111 myself->pid, myself->sid);
1113 /* CGF FIXME: This can't be right. */
1114 if (tp->getsid () == myself->sid)
1115 tp->kill_pgrp (SIGHUP);
1124 cygwin_atexit (void (*fn) (void))
1127 dll *d = dlls.find ((void *) _my_tls.retaddr ());
1128 res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
1135 exit_state = ES_EXIT_STARTING;
1142 do_exit (((DWORD) n & 0xff) << 8);
1145 extern "C" void cygwin_stackdump ();
1148 vapi_fatal (const char *fmt, va_list ap)
1151 int n = __small_sprintf (buf, "%P: *** fatal error %s- ", in_forkee ? "in forked process " : "");
1152 __small_vsprintf (buf + n, fmt, ap);
1154 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1159 cygwin_stackdump ();
1160 myself.exit (__api_fatal_exit_val);
1164 api_fatal (const char *fmt, ...)
1169 vapi_fatal (fmt, ap);
1173 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1175 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1177 child_proc_info->type = _CH_WHOOPS;
1181 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1184 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1185 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1187 api_fatal ("%s mismatch detected - %p/%p.\n\
1188 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1189 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1190 and delete all but the most recent version. The most recent version *should*\n\
1191 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1192 installed the cygwin distribution. Rebooting is also suggested if you\n\
1193 are unable to find another cygwin DLL.",
1194 what, magic_version, version);
1199 cygbench (const char *s)
1201 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1202 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());