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"
41 #define MAX_AT_FILE_LEVEL 10
43 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
45 extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
46 extern "C" void __sinit (_reent *);
48 static int NO_COPY envc;
49 static char NO_COPY **envp;
51 static char title_buf[TITLESIZE + 1];
53 bool NO_COPY jit_debug;
58 void (**pfunc) () = user_data->dtors;
61 user_data->dtors = NULL;
68 do_global_ctors (void (**in_pfunc)(), int force)
70 if (!force && in_forkee)
71 return; // inherit constructed stuff from parent pid
73 /* Run ctors backwards, so skip the first entry and find how many
74 there are, then run them. */
76 void (**pfunc) () = in_pfunc;
80 while (--pfunc > in_pfunc)
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.
91 insert_file (char *name, char *&cmd)
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 */
107 if (f == INVALID_HANDLE_VALUE)
109 debug_printf ("couldn't open file '%s', %E", name);
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)
119 debug_printf ("couldn't get file size for '%s', %E", name);
123 int new_size = strlen (cmd) + size + 2;
124 char *tmp = (char *) malloc (new_size);
127 debug_printf ("malloc failed, %E");
131 /* realloc passed as it should */
134 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
136 if (!rf_result || (rf_read != size))
138 debug_printf ("ReadFile failed, %E");
143 strcpy (tmp + size, cmd);
152 return ch == '"' || ch == '\'';
155 /* Step over a run of characters delimited by quotes */
156 static /*__inline*/ char *
157 quoted (char *cmd, int winshell)
165 strcpy (cmd, cmd + 1);
166 if (*(p = strechr (cmd, quote)))
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)
177 cmd = strchr (cmd, '\0'); // no closing quote
182 else if (quote == '"' && p[1] == '"')
185 cmd = ++p; // a quoted quote
189 cmd = p + 1; // point to after end
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. */
199 globify (char *word, char **&argv, int &argc, int &argvlen)
201 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
206 int dos_spec = isdrive (word);
207 if (!dos_spec && isquote (*word) && word[1] && word[2])
208 dos_spec = isdrive (word + 1);
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, "'\""))
215 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
217 /* Fill pattern with characters from word, quoting any
218 characters found within quotes. */
219 for (p = pattern, s = word; *s != '\000'; s++, p++)
222 if (dos_spec && *s == '\\')
229 while (*++s && *s != quote)
231 if (dos_spec || *s != '\\')
233 else if (s[1] == quote || s[1] == '\\')
236 size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
237 if (cnt <= 1 || cnt == (size_t)-1)
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)
261 /* Allocate enough space in argv for the matched filenames. */
263 if ((argc += gl.gl_pathc) > argvlen)
266 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
269 /* Copy the matched filenames to argv. */
270 char **gv = gl.gl_pathv;
271 char **av = argv + n;
274 debug_printf ("argv[%d] = '%s'", n++, *gv);
278 /* Clean up after glob. */
283 /* Build argv, argc from string passed from Windows. */
285 static void __stdcall
286 build_argv (char *cmd, char **&argv, int &argc, int winshell)
289 int nesting = 0; // monitor "nesting" from insert_file
295 /* Scan command line until there is nothing left. */
305 /* Found the beginning of an argument. */
307 char *sawquote = NULL;
310 if (*cmd != '"' && (!winshell || *cmd != '\''))
311 cmd++; // Skip over this character
313 /* Skip over characters until the closing quote */
316 cmd = quoted (cmd, winshell && argc > 0);
318 if (issep (*cmd)) // End of argument if space
322 *cmd++ = '\0'; // Terminate `word'
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 == '@')
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
334 /* See if we need to allocate more space for argv */
338 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
341 /* Add word to argv file after (optional) wildcard expansion. */
342 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
344 debug_printf ("argv[%d] = '%s'", argc, word);
351 debug_printf ("argc %d", argc);
354 /* sanity and sync check */
356 check_sanity_and_sync (per_process *p)
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");
364 /* Make sure that the app and the dll are in sync. */
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);
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);
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);
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
385 __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
388 child_info NO_COPY *child_proc_info = NULL;
390 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
393 child_info_fork::alloc_stack_hard_way (volatile char *b)
398 /* First check if the requested stack area is part of the user heap
399 or part of a mmapped region. If so, we have been started from a
400 pthread with an application-provided stack, and the stack has just
402 if ((stacktop >= cygheap->user_heap.base
403 && stackbottom <= cygheap->user_heap.max)
404 || is_mmapped_region ((caddr_t) stacktop, (caddr_t) stackbottom))
407 /* First, try to reserve the entire stack. */
408 stacksize = (char *) stackbottom - (char *) stackaddr;
409 if (!VirtualAlloc (stackaddr, stacksize, MEM_RESERVE, PAGE_NOACCESS))
410 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
411 stackaddr, stackbottom);
412 stacksize = (char *) stackbottom - (char *) stacktop;
413 stack_ptr = VirtualAlloc (stacktop, stacksize, MEM_COMMIT,
414 PAGE_EXECUTE_READWRITE);
416 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
417 stacktop, stacksize);
418 if (guardsize != (size_t) -1)
420 /* Allocate PAGE_GUARD page if it still fits. */
421 if (stack_ptr > stackaddr)
423 stack_ptr = (void *) ((LPBYTE) stack_ptr
424 - wincap.page_size ());
425 if (!VirtualAlloc (stack_ptr, wincap.page_size (), MEM_COMMIT,
427 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
430 /* Allocate POSIX guard pages. */
432 VirtualAlloc (stackaddr, guardsize, MEM_COMMIT, PAGE_NOACCESS);
437 void *getstack (void *) __attribute__ ((noinline));
439 getstack (volatile char * volatile p)
446 /* extend the stack prior to fork longjmp */
449 child_info_fork::alloc_stack ()
451 volatile char * volatile esp;
452 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
453 if (_tlsbase != stackbottom)
454 alloc_stack_hard_way (esp);
457 char *st = (char *) stacktop - 4096;
458 while (_tlstop >= st)
459 esp = getstack (esp);
467 static int NO_COPY sent_break;
470 debug_printf ("break here");
476 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
480 char buf[NT_MAX_PATH];
483 if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
485 DWORD ms = atoi (buf);
486 console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
488 if (!strace.active () && !dynamically_loaded)
491 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
493 char buf1[NT_MAX_PATH];
494 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
497 char *p = strpbrk (buf, ":=");
499 p = (char *) "gdb.exe -nw";
502 if (strstr (buf1, buf))
504 error_start_init (p);
507 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
516 get_cygwin_startup_info ()
520 GetStartupInfo (&si);
521 child_info *res = (child_info *) si.lpReserved2;
523 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
524 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
528 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
529 multiple_cygwin_problem ("proc intro", res->intro, 0);
530 else if (res->cygheap != (void *) &_cygheap_start)
531 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
532 (DWORD) &_cygheap_start);
534 unsigned should_be_cb = 0;
539 should_be_cb = sizeof (child_info_fork);
544 should_be_cb = sizeof (child_info_spawn);
545 if (should_be_cb != res->cb)
546 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
547 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
548 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
549 if (res->isstraced ())
552 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
558 system_printf ("unknown exec type %d", res->type);
559 /* intentionally fall through */
569 #define dll_data_start &_data_start__
570 #define dll_data_end &_data_end__
571 #define dll_bss_start &_bss_start__
572 #define dll_bss_end &_bss_end__
575 child_info_fork::handle_fork ()
577 cygheap_fixup_in_child (false);
579 myself.thisproc (NULL);
580 myself->uid = cygheap->user.real_uid;
581 myself->gid = cygheap->user.real_gid;
583 child_copy (parent, false,
584 "dll data", dll_data_start, dll_data_end,
585 "dll bss", dll_bss_start, dll_bss_end,
586 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
589 /* Do the relocations here. These will actually likely be overwritten by the
590 below child_copy but we do them here in case there is a read-only section
591 which does not get copied by fork. */
592 _pei386_runtime_relocator (user_data);
594 /* step 2 now that the dll has its heap filled in, we can fill in the
595 user's data and bss since user_data is now filled out. */
596 child_copy (parent, false,
597 "data", user_data->data_start, user_data->data_end,
598 "bss", user_data->bss_start, user_data->bss_end,
601 if (fixup_mmaps_after_fork (parent))
602 api_fatal ("recreate_mmaps_after_fork_failed");
606 child_info_spawn::handle_spawn ()
608 extern void fixup_lockf_after_exec ();
610 cygheap_fixup_in_child (true);
612 if (!moreinfo->myself_pinfo ||
613 !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
614 GetCurrentProcess (), &h, 0,
615 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
618 __argc = moreinfo->argc;
619 __argv = moreinfo->argv;
620 envp = moreinfo->envp;
621 envc = moreinfo->envc;
622 if (!dynamically_loaded)
623 cygheap->fdtab.fixup_after_exec ();
625 cygheap->fdtab.move_fd (__stdin, 0);
627 cygheap->fdtab.move_fd (__stdout, 1);
628 cygheap->user.groups.clear_supp ();
632 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
633 handles might get confused. */
634 CloseHandle (child_proc_info->parent);
635 child_proc_info->parent = NULL;
637 signal_fixup_after_exec ();
638 if (moreinfo->old_title)
640 old_title = strcpy (title_buf, moreinfo->old_title);
641 cfree (moreinfo->old_title);
643 fixup_lockf_after_exec ();
646 /* Retrieve and store system directory for later use. Note that the
647 directory is stored with a trailing backslash! */
649 init_windows_system_directory ()
651 windows_system_directory_length =
652 GetSystemDirectoryW (windows_system_directory, MAX_PATH);
653 if (windows_system_directory_length == 0)
654 api_fatal ("can't find windows system directory");
655 windows_system_directory[windows_system_directory_length++] = L'\\';
656 windows_system_directory[windows_system_directory_length] = L'\0';
662 init_windows_system_directory ();
663 init_global_security ();
666 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
668 lock_process::init ();
669 _impure_ptr = _GLOBAL_REENT;
670 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
671 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
672 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
673 _impure_ptr->_current_locale = "C";
674 user_data->impure_ptr = _impure_ptr;
675 user_data->impure_ptr_ptr = &_impure_ptr;
677 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
678 GetCurrentProcess (), &hMainThread,
679 0, false, DUPLICATE_SAME_ACCESS);
681 NtOpenProcessToken (NtCurrentProcess (), MAXIMUM_ALLOWED, &hProcToken);
682 set_cygwin_privileges (hProcToken);
685 do_global_ctors (&__CTOR_LIST__, 1);
688 child_proc_info = get_cygwin_startup_info ();
689 if (!child_proc_info)
693 cygwin_user_h = child_proc_info->user_h;
694 switch (child_proc_info->type)
697 fork_info->handle_fork ();
701 spawn_info->handle_spawn ();
706 user_data->threadinterface->Init ();
710 /* Initialize events */
712 tty_list::init_session ();
714 _main_tls = &_my_tls;
716 /* Initialize signal processing here, early, in the hopes that the creation
717 of a thread early in the process will cause more predictability in memory
718 layout for the main thread. */
719 if (!wincap.has_buggy_thread_startup () && !dynamically_loaded)
722 debug_printf ("finished dll_crt0_0 initialization");
725 /* Take over from libc's crt0.o and start the application. Note the
726 various special cases when Cygwin DLL is being runtime loaded (as
727 opposed to being link-time loaded by Cygwin apps) from a non
728 cygwin app via LoadLibrary. */
732 extern void initial_setlocale ();
734 if (wincap.has_buggy_thread_startup () || dynamically_loaded)
736 check_sanity_and_sync (user_data);
738 /* Initialize malloc and then call user_shared_initialize since it relies
739 on a functioning malloc and it's possible that the user's program may
740 have overridden malloc. We only know about that at this stage,
743 user_shared->initialize ();
747 const int n = 2 * 1024 * 1024;
750 void *p = cmalloc (HEAP_STR, n);
752 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
755 small_printf ("total allocated %p\n", (i - 1) * n);
761 ProtectHandle (hMainThread);
763 cygheap->cwd.init ();
765 /* Initialize pthread mainthread when not forked and it is safe to call new,
766 otherwise it is reinitalized in fixup_after_fork */
769 pthread::init_mainthread ();
770 _pei386_runtime_relocator (user_data);
774 strace.microseconds ();
777 create_signal_arrived (); /* FIXME: move into wait_sig? */
779 /* Initialize debug muto, if DLL is built with --enable-debugging.
780 Need to do this before any helper threads start. */
784 cygheap->fdtab.vfork_child_fixup ();
785 main_vfork = vfork_storage.create ();
788 cygbench ("pre-forkee");
791 /* If we've played with the stack, stacksize != 0. That means that
792 fork() was invoked from other than the main thread. Make sure that
793 frame pointer is referencing the new stack so that the OS knows what
794 to do when it needs to increase the size of the stack.
796 NOTE: Don't do anything that involves the stack until you've completed
798 if (fork_info->stackaddr)
800 _tlsbase = (char *) fork_info->stackbottom;
801 _tlstop = (char *) fork_info->stacktop;
804 longjmp (fork_info->jmp, true);
807 __sinit (_impure_ptr);
811 extern void fork_init ();
815 pinfo_init (envp, envc);
817 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
818 old_title = title_buf;
820 /* Allocate cygheap->fdtab */
823 uinfo_init (); /* initialize user info */
825 /* Connect to tty. */
826 tty::init_session ();
828 /* Set internal locale to the environment settings. */
829 initial_setlocale ();
833 PWCHAR wline = GetCommandLineW ();
834 size_t size = sys_wcstombs (NULL, 0, wline);
835 char *line = (char *) alloca (size);
836 sys_wcstombs (line, size, wline);
838 /* Scan the command line and build argv. Expand wildcards if not
839 called from another cygwin process. */
840 build_argv (line, __argv, __argc,
841 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
843 /* Convert argv[0] to posix rules if it's currently blatantly
845 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
847 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
848 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
849 new_argv0, NT_MAX_PATH);
850 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
854 __argc_safe = __argc;
855 if (user_data->premain[0])
856 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
857 user_data->premain[i] (__argc, __argv, user_data);
859 /* Set up standard fds in file descriptor table. */
860 cygheap->fdtab.stdio_init ();
862 /* Set up __progname for getopt error call. */
863 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
866 __progname = __argv[0];
867 program_invocation_name = __argv[0];
868 program_invocation_short_name = __progname;
871 char *cp = strchr (__progname, '\0') - 4;
872 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
876 /* Set new console title if appropriate. */
878 if (display_title && !dynamically_loaded)
880 char *cp = __progname;
881 if (strip_title_path)
882 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
885 set_console_title (cp);
888 (void) xdr_set_vprintf (&cygxdr_vwarnx);
889 cygwin_finished_initializing = true;
890 /* Call init of loaded dlls. */
893 /* Execute any specified "premain" functions */
894 if (user_data->premain[PREMAIN_LEN / 2])
895 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
896 user_data->premain[i] (__argc, __argv, user_data);
900 if (dynamically_loaded)
902 _setlocale_r (_REENT, LC_CTYPE, "C");
906 /* Disable case-insensitive globbing */
907 ignore_case_with_glob = false;
910 cygbench (__progname);
913 /* Per POSIX set the default application locale back to "C". */
914 _setlocale_r (_REENT, LC_CTYPE, "C");
917 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
919 .global __cygwin_exit_return \n\
920 __cygwin_exit_return: \n\
924 extern "C" void __stdcall
930 main_environ = user_data->envptr;
933 fork_info->alloc_stack ();
934 _main_tls = &_my_tls;
937 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
941 dll_crt0 (per_process *uptr)
943 /* Set the local copy of the pointer into the user space. */
944 if (!in_forkee && uptr && uptr != user_data)
946 memcpy (user_data, uptr, per_process_overwrite);
947 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
952 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
953 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
954 calling this function, and that storage must not be overwritten until you
955 unload cygwin1.dll, as it is used for _my_tls. It is best to load
956 cygwin1.dll before spawning any additional threads in your process.
958 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
959 from MSVC and non-cygwin MinGW applications. */
966 user_data->magic_biscuit = sizeof (per_process);
968 user_data->envptr = &envp;
969 user_data->fmode_ptr = &_fmode;
977 /* Ordering is critical here. DLL ctors have already been
978 run as they were being loaded, so we should stack the
979 queued call to DLL dtors now. */
980 atexit (dll_global_dtors);
981 do_global_ctors (user_data->ctors, false);
982 /* Now we have run global ctors, register their dtors.
984 At exit, global dtors will run first, so the app can still
985 use shared library functions while terminating; then the
986 DLLs will be destroyed; finally newlib will shut down stdio
987 and terminate itself. */
988 atexit (do_global_dtors);
989 sig_dispatch_pending (true);
995 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
998 vfork_save *vf = vfork_storage.val ();
999 if (vf != NULL && vf->pid < 0)
1001 exit_state = ES_NOT_EXITING;
1002 vf->restore_exit (status);
1006 lock_process until_exit (true);
1008 if (exit_state < ES_EVENTS_TERMINATE)
1010 exit_state = ES_EVENTS_TERMINATE;
1011 events_terminate ();
1014 if (exit_state < ES_SIGNAL)
1016 exit_state = ES_SIGNAL;
1017 signal (SIGCHLD, SIG_IGN);
1018 signal (SIGHUP, SIG_IGN);
1019 signal (SIGINT, SIG_IGN);
1020 signal (SIGQUIT, SIG_IGN);
1023 if (exit_state < ES_CLOSEALL)
1025 exit_state = ES_CLOSEALL;
1029 UINT n = (UINT) status;
1030 if (exit_state < ES_THREADTERM)
1032 exit_state = ES_THREADTERM;
1033 cygthread::terminate ();
1036 myself->stopsig = 0;
1038 if (exit_state < ES_HUP_PGRP)
1040 exit_state = ES_HUP_PGRP;
1041 /* Kill orphaned children on group leader exit */
1042 if (myself->has_pgid_children && myself->pid == myself->pgid)
1045 si.si_signo = -SIGHUP;
1046 si.si_code = SI_KERNEL;
1047 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1048 myself->pid, myself->pgid);
1049 kill_pgrp (myself->pgid, si);
1053 if (exit_state < ES_HUP_SID)
1055 exit_state = ES_HUP_SID;
1056 /* Kill the foreground process group on session leader exit */
1057 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1059 tty *tp = cygwin_shared->tty[myself->ctty];
1060 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1061 myself->pid, myself->sid);
1063 /* CGF FIXME: This can't be right. */
1064 if (tp->getsid () == myself->sid)
1065 tp->kill_pgrp (SIGHUP);
1070 if (exit_state < ES_TITLE)
1072 exit_state = ES_TITLE;
1073 /* restore console title */
1074 if (old_title && display_title)
1075 set_console_title (old_title);
1078 if (exit_state < ES_TTY_TERMINATE)
1080 exit_state = ES_TTY_TERMINATE;
1081 cygwin_shared->tty.terminate ();
1088 cygwin_atexit (void (*fn) (void))
1091 dll *d = dlls.find ((void *) _my_tls.retaddr ());
1092 res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
1099 exit_state = ES_EXIT_STARTING;
1106 do_exit (((DWORD) n & 0xff) << 8);
1109 extern "C" void cygwin_stackdump ();
1112 vapi_fatal (const char *fmt, va_list ap)
1115 int n = __small_sprintf (buf, "%P: *** fatal error %s- ", in_forkee ? "in forked process " : "");
1116 __small_vsprintf (buf + n, fmt, ap);
1118 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1123 cygwin_stackdump ();
1124 myself.exit (__api_fatal_exit_val);
1128 api_fatal (const char *fmt, ...)
1133 vapi_fatal (fmt, ap);
1137 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1139 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1141 child_proc_info->type = _PROC_WHOOPS;
1145 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1148 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1149 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1151 api_fatal ("%s mismatch detected - %p/%p.\n\
1152 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1153 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1154 and delete all but the most recent version. The most recent version *should*\n\
1155 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1156 installed the cygwin distribution. Rebooting is also suggested if you\n\
1157 are unable to find another cygwin DLL.",
1158 what, magic_version, version);
1163 cygbench (const char *s)
1165 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1166 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());