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 bool NO_COPY jit_debug;
56 void (**pfunc) () = user_data->dtors;
59 user_data->dtors = NULL;
66 do_global_ctors (void (**in_pfunc)(), int force)
68 if (!force && in_forkee)
69 return; // inherit constructed stuff from parent pid
71 /* Run ctors backwards, so skip the first entry and find how many
72 there are, then run them. */
74 void (**pfunc) () = in_pfunc;
78 while (--pfunc > in_pfunc)
83 * Replaces @file in the command line with the contents of the file.
84 * There may be multiple @file's in a single command line
85 * A \@file is replaced with @file so that echo \@foo would print
86 * @foo and not the contents of foo.
89 insert_file (char *name, char *&cmd)
95 PWCHAR wname = tp.w_get ();
96 sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
97 f = CreateFileW (wname,
98 GENERIC_READ, /* open for reading */
99 FILE_SHARE_VALID_FLAGS, /* share for reading */
100 &sec_none_nih, /* default security */
101 OPEN_EXISTING, /* existing file only */
102 FILE_ATTRIBUTE_NORMAL, /* normal file */
103 NULL); /* no attr. template */
105 if (f == INVALID_HANDLE_VALUE)
107 debug_printf ("couldn't open file '%s', %E", name);
111 /* This only supports files up to about 4 billion bytes in
112 size. I am making the bold assumption that this is big
113 enough for this feature */
114 size = GetFileSize (f, NULL);
115 if (size == 0xFFFFFFFF)
117 debug_printf ("couldn't get file size for '%s', %E", name);
121 int new_size = strlen (cmd) + size + 2;
122 char *tmp = (char *) malloc (new_size);
125 debug_printf ("malloc failed, %E");
129 /* realloc passed as it should */
132 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
134 if (!rf_result || (rf_read != size))
136 debug_printf ("ReadFile failed, %E");
141 strcpy (tmp + size, cmd);
150 return ch == '"' || ch == '\'';
153 /* Step over a run of characters delimited by quotes */
154 static /*__inline*/ char *
155 quoted (char *cmd, int winshell)
163 strcpy (cmd, cmd + 1);
164 if (*(p = strechr (cmd, quote)))
169 const char *s = quote == '\'' ? "'" : "\\\"";
170 /* This must have been run from a Windows shell, so preserve
171 quotes for globify to play with later. */
172 while (*cmd && *++cmd)
173 if ((p = strpbrk (cmd, s)) == NULL)
175 cmd = strchr (cmd, '\0'); // no closing quote
180 else if (quote == '"' && p[1] == '"')
183 cmd = ++p; // a quoted quote
187 cmd = p + 1; // point to after end
193 /* Perform a glob on word if it contains wildcard characters.
194 Also quote every character between quotes to force glob to
195 treat the characters literally. */
197 globify (char *word, char **&argv, int &argc, int &argvlen)
199 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
204 int dos_spec = isdrive (word);
205 if (!dos_spec && isquote (*word) && word[1] && word[2])
206 dos_spec = isdrive (word + 1);
208 /* We'll need more space if there are quoting characters in
209 word. If that is the case, doubling the size of the
210 string should provide more than enough space. */
211 if (strpbrk (word, "'\""))
213 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
215 /* Fill pattern with characters from word, quoting any
216 characters found within quotes. */
217 for (p = pattern, s = word; *s != '\000'; s++, p++)
220 if (dos_spec && *s == '\\')
227 while (*++s && *s != quote)
229 if (dos_spec || *s != '\\')
231 else if (s[1] == quote || s[1] == '\\')
234 size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
235 if (cnt <= 1 || cnt == (size_t)-1)
255 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
256 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
259 /* Allocate enough space in argv for the matched filenames. */
261 if ((argc += gl.gl_pathc) > argvlen)
264 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
267 /* Copy the matched filenames to argv. */
268 char **gv = gl.gl_pathv;
269 char **av = argv + n;
272 debug_printf ("argv[%d] = '%s'", n++, *gv);
276 /* Clean up after glob. */
281 /* Build argv, argc from string passed from Windows. */
283 static void __stdcall
284 build_argv (char *cmd, char **&argv, int &argc, int winshell)
287 int nesting = 0; // monitor "nesting" from insert_file
293 /* Scan command line until there is nothing left. */
303 /* Found the beginning of an argument. */
305 char *sawquote = NULL;
308 if (*cmd != '"' && (!winshell || *cmd != '\''))
309 cmd++; // Skip over this character
311 /* Skip over characters until the closing quote */
314 cmd = quoted (cmd, winshell && argc > 0);
316 if (issep (*cmd)) // End of argument if space
320 *cmd++ = '\0'; // Terminate `word'
322 /* Possibly look for @file construction assuming that this isn't
323 the very first argument and the @ wasn't quoted */
324 if (argc && sawquote != word && *word == '@')
326 if (++nesting > MAX_AT_FILE_LEVEL)
327 api_fatal ("Too many levels of nesting for %s", word);
328 if (insert_file (word, cmd))
329 continue; // There's new stuff in cmd now
332 /* See if we need to allocate more space for argv */
336 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
339 /* Add word to argv file after (optional) wildcard expansion. */
340 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
342 debug_printf ("argv[%d] = '%s'", argc, word);
349 debug_printf ("argc %d", argc);
352 /* sanity and sync check */
354 check_sanity_and_sync (per_process *p)
356 /* Sanity check to make sure developers didn't change the per_process */
357 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
358 /* about changing it]. */
359 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
360 api_fatal ("per_process sanity check failed");
362 /* Make sure that the app and the dll are in sync. */
364 /* Complain if older than last incompatible change */
365 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
366 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
367 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
369 /* magic_biscuit != 0 if using the old style version numbering scheme. */
370 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
371 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
372 p->magic_biscuit, SIZEOF_PER_PROCESS);
374 /* Complain if incompatible API changes made */
375 if (p->api_major > cygwin_version.api_major)
376 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
377 p->api_major, cygwin_version.api_major);
379 /* This is a kludge to work around a version of _cygwin_common_crt0
380 which overwrote the cxx_malloc field with the local DLL copy.
381 Hilarity ensues if the DLL is not loaded while the process
383 __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
386 child_info NO_COPY *child_proc_info = NULL;
388 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
391 child_info_fork::alloc_stack_hard_way (volatile char *b)
396 /* First check if the requested stack area is part of the user heap
397 or part of a mmapped region. If so, we have been started from a
398 pthread with an application-provided stack, and the stack has just
400 if ((stacktop >= cygheap->user_heap.base
401 && stackbottom <= cygheap->user_heap.max)
402 || is_mmapped_region ((caddr_t) stacktop, (caddr_t) stackbottom))
405 /* First, try to reserve the entire stack. */
406 stacksize = (char *) stackbottom - (char *) stackaddr;
407 if (!VirtualAlloc (stackaddr, stacksize, MEM_RESERVE, PAGE_NOACCESS))
408 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
409 stackaddr, stackbottom);
410 stacksize = (char *) stackbottom - (char *) stacktop;
411 stack_ptr = VirtualAlloc (stacktop, stacksize, MEM_COMMIT,
412 PAGE_EXECUTE_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 if (_tlsbase != stackbottom)
451 alloc_stack_hard_way (esp);
454 char *st = (char *) stacktop - 4096;
455 while (_tlstop >= st)
456 esp = getstack (esp);
464 static int NO_COPY sent_break;
467 debug_printf ("break here");
473 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
478 char buf[NT_MAX_PATH];
479 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
481 char buf1[NT_MAX_PATH];
482 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
485 char *p = strpbrk (buf, ":=");
487 p = (char *) "gdb.exe -nw";
490 if (strstr (buf1, buf))
492 error_start_init (p);
495 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
503 get_cygwin_startup_info ()
507 GetStartupInfo (&si);
508 child_info *res = (child_info *) si.lpReserved2;
510 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
511 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
513 strace.activate (false);
518 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
519 multiple_cygwin_problem ("proc intro", res->intro, 0);
520 else if (res->cygheap != (void *) &_cygheap_start)
521 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
522 (DWORD) &_cygheap_start);
524 unsigned should_be_cb = 0;
529 should_be_cb = sizeof (child_info_fork);
534 should_be_cb = sizeof (child_info_spawn);
535 if (should_be_cb != res->cb)
536 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
537 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
538 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
539 if (res->isstraced ())
541 while (!being_debugged ())
543 strace.activate (res->type == _CH_FORK);
547 system_printf ("unknown exec type %d", res->type);
548 /* intentionally fall through */
558 #define dll_data_start &_data_start__
559 #define dll_data_end &_data_end__
560 #define dll_bss_start &_bss_start__
561 #define dll_bss_end &_bss_end__
564 child_info_fork::handle_fork ()
566 cygheap_fixup_in_child (false);
568 myself.thisproc (NULL);
569 myself->uid = cygheap->user.real_uid;
570 myself->gid = cygheap->user.real_gid;
572 child_copy (parent, false,
573 "dll data", dll_data_start, dll_data_end,
574 "dll bss", dll_bss_start, dll_bss_end,
575 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
578 /* Do the relocations here. These will actually likely be overwritten by the
579 below child_copy but we do them here in case there is a read-only section
580 which does not get copied by fork. */
581 _pei386_runtime_relocator (user_data);
583 /* step 2 now that the dll has its heap filled in, we can fill in the
584 user's data and bss since user_data is now filled out. */
585 child_copy (parent, false,
586 "data", user_data->data_start, user_data->data_end,
587 "bss", user_data->bss_start, user_data->bss_end,
590 if (fixup_mmaps_after_fork (parent))
591 api_fatal ("recreate_mmaps_after_fork_failed");
595 child_info_spawn::handle_spawn ()
597 extern void fixup_lockf_after_exec ();
599 cygheap_fixup_in_child (true);
601 if (!moreinfo->myself_pinfo ||
602 !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
603 GetCurrentProcess (), &h, 0,
604 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
607 __argc = moreinfo->argc;
608 __argv = moreinfo->argv;
609 envp = moreinfo->envp;
610 envc = moreinfo->envc;
611 if (!dynamically_loaded)
612 cygheap->fdtab.fixup_after_exec ();
614 cygheap->fdtab.move_fd (__stdin, 0);
616 cygheap->fdtab.move_fd (__stdout, 1);
617 cygheap->user.groups.clear_supp ();
619 /* If we're execing we may have "inherited" a list of children forked by the
620 previous process executing under this pid. Reattach them here so that we
621 can wait for them. */
622 if (type == _CH_EXEC)
623 reattach_children ();
627 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
628 handles might get confused. */
629 CloseHandle (child_proc_info->parent);
630 child_proc_info->parent = NULL;
632 signal_fixup_after_exec ();
633 fixup_lockf_after_exec ();
636 /* Retrieve and store system directory for later use. Note that the
637 directory is stored with a trailing backslash! */
639 init_windows_system_directory ()
641 windows_system_directory_length =
642 GetSystemDirectoryW (windows_system_directory, MAX_PATH);
643 if (windows_system_directory_length == 0)
644 api_fatal ("can't find windows system directory");
645 windows_system_directory[windows_system_directory_length++] = L'\\';
646 windows_system_directory[windows_system_directory_length] = L'\0';
652 child_proc_info = get_cygwin_startup_info ();
653 init_windows_system_directory ();
654 init_global_security ();
657 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
659 lock_process::init ();
660 _impure_ptr = _GLOBAL_REENT;
661 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
662 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
663 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
664 _impure_ptr->_current_locale = "C";
665 user_data->impure_ptr = _impure_ptr;
666 user_data->impure_ptr_ptr = &_impure_ptr;
668 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
669 GetCurrentProcess (), &hMainThread,
670 0, false, DUPLICATE_SAME_ACCESS);
672 NtOpenProcessToken (NtCurrentProcess (), MAXIMUM_ALLOWED, &hProcToken);
673 set_cygwin_privileges (hProcToken);
676 do_global_ctors (&__CTOR_LIST__, 1);
679 if (!child_proc_info)
683 cygwin_user_h = child_proc_info->user_h;
684 switch (child_proc_info->type)
687 fork_info->handle_fork ();
691 spawn_info->handle_spawn ();
696 user_data->threadinterface->Init ();
700 /* Initialize events */
702 tty_list::init_session ();
704 _main_tls = &_my_tls;
706 /* Initialize signal processing here, early, in the hopes that the creation
707 of a thread early in the process will cause more predictability in memory
708 layout for the main thread. */
709 if (!dynamically_loaded)
712 debug_printf ("finished dll_crt0_0 initialization");
715 /* Take over from libc's crt0.o and start the application. Note the
716 various special cases when Cygwin DLL is being runtime loaded (as
717 opposed to being link-time loaded by Cygwin apps) from a non
718 cygwin app via LoadLibrary. */
722 extern void initial_setlocale ();
724 if (dynamically_loaded)
727 check_sanity_and_sync (user_data);
729 /* Initialize malloc and then call user_shared_initialize since it relies
730 on a functioning malloc and it's possible that the user's program may
731 have overridden malloc. We only know about that at this stage,
734 user_shared->initialize ();
738 const int n = 2 * 1024 * 1024;
741 void *p = cmalloc (HEAP_STR, n);
743 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
746 small_printf ("total allocated %p\n", (i - 1) * n);
752 ProtectHandle (hMainThread);
754 cygheap->cwd.init ();
756 /* Initialize pthread mainthread when not forked and it is safe to call new,
757 otherwise it is reinitalized in fixup_after_fork */
760 pthread::init_mainthread ();
761 _pei386_runtime_relocator (user_data);
765 strace.microseconds ();
768 create_signal_arrived (); /* FIXME: move into wait_sig? */
770 /* Initialize debug muto, if DLL is built with --enable-debugging.
771 Need to do this before any helper threads start. */
775 cygheap->fdtab.vfork_child_fixup ();
776 main_vfork = vfork_storage.create ();
779 cygbench ("pre-forkee");
782 /* If we've played with the stack, stacksize != 0. That means that
783 fork() was invoked from other than the main thread. Make sure that
784 frame pointer is referencing the new stack so that the OS knows what
785 to do when it needs to increase the size of the stack.
787 NOTE: Don't do anything that involves the stack until you've completed
789 if (fork_info->stackaddr)
791 _tlsbase = (char *) fork_info->stackbottom;
792 _tlstop = (char *) fork_info->stacktop;
795 longjmp (fork_info->jmp, true);
798 __sinit (_impure_ptr);
802 extern void fork_init ();
806 pinfo_init (envp, envc);
809 /* Allocate cygheap->fdtab */
812 uinfo_init (); /* initialize user info */
814 /* Connect to tty. */
815 tty::init_session ();
817 /* Set internal locale to the environment settings. */
818 initial_setlocale ();
822 PWCHAR wline = GetCommandLineW ();
823 size_t size = sys_wcstombs (NULL, 0, wline);
824 char *line = (char *) alloca (size);
825 sys_wcstombs (line, size, wline);
827 /* Scan the command line and build argv. Expand wildcards if not
828 called from another cygwin process. */
829 build_argv (line, __argv, __argc,
830 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
832 /* Convert argv[0] to posix rules if it's currently blatantly
834 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
836 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
837 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
838 new_argv0, NT_MAX_PATH);
839 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
843 __argc_safe = __argc;
844 if (user_data->premain[0])
845 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
846 user_data->premain[i] (__argc, __argv, user_data);
848 /* Set up standard fds in file descriptor table. */
849 cygheap->fdtab.stdio_init ();
851 /* Set up __progname for getopt error call. */
852 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
855 __progname = __argv[0];
856 program_invocation_name = __argv[0];
857 program_invocation_short_name = __progname;
860 char *cp = strchr (__progname, '\0') - 4;
861 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
865 (void) xdr_set_vprintf (&cygxdr_vwarnx);
866 cygwin_finished_initializing = true;
867 /* Call init of loaded dlls. */
870 /* Execute any specified "premain" functions */
871 if (user_data->premain[PREMAIN_LEN / 2])
872 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
873 user_data->premain[i] (__argc, __argv, user_data);
877 if (dynamically_loaded)
879 _setlocale_r (_REENT, LC_CTYPE, "C");
883 /* Disable case-insensitive globbing */
884 ignore_case_with_glob = false;
887 cygbench (__progname);
890 /* Per POSIX set the default application locale back to "C". */
891 _setlocale_r (_REENT, LC_CTYPE, "C");
895 /* Create a copy of Cygwin's version of __argv so that, if the user makes
896 a change to an element of argv[] it does not affect Cygwin's argv.
897 Changing the the contents of what argv[n] points to will still
898 affect Cygwin. This is similar (but not exactly like) Linux. */
899 char *newargv[__argc + 1];
900 char **nav = newargv;
902 while ((*nav++ = *oav++) != NULL)
904 cygwin_exit (user_data->main (__argc, newargv, *user_data->envptr));
907 .global __cygwin_exit_return \n\
908 __cygwin_exit_return: \n\
912 extern "C" void __stdcall
918 main_environ = user_data->envptr;
921 fork_info->alloc_stack ();
922 _main_tls = &_my_tls;
925 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
929 dll_crt0 (per_process *uptr)
931 /* Set the local copy of the pointer into the user space. */
932 if (!in_forkee && uptr && uptr != user_data)
934 memcpy (user_data, uptr, per_process_overwrite);
935 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
940 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
941 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
942 calling this function, and that storage must not be overwritten until you
943 unload cygwin1.dll, as it is used for _my_tls. It is best to load
944 cygwin1.dll before spawning any additional threads in your process.
946 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
947 from MSVC and non-cygwin MinGW applications. */
954 user_data->magic_biscuit = sizeof (per_process);
956 user_data->envptr = &envp;
957 user_data->fmode_ptr = &_fmode;
965 /* Ordering is critical here. DLL ctors have already been
966 run as they were being loaded, so we should stack the
967 queued call to DLL dtors now. */
968 atexit (dll_global_dtors);
969 do_global_ctors (user_data->ctors, false);
970 /* Now we have run global ctors, register their dtors.
972 At exit, global dtors will run first, so the app can still
973 use shared library functions while terminating; then the
974 DLLs will be destroyed; finally newlib will shut down stdio
975 and terminate itself. */
976 atexit (do_global_dtors);
977 sig_dispatch_pending (true);
983 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
986 vfork_save *vf = vfork_storage.val ();
987 if (vf != NULL && vf->pid < 0)
989 exit_state = ES_NOT_EXITING;
990 vf->restore_exit (status);
994 lock_process until_exit (true);
996 if (exit_state < ES_EVENTS_TERMINATE)
998 exit_state = ES_EVENTS_TERMINATE;
1002 if (exit_state < ES_SIGNAL)
1004 exit_state = ES_SIGNAL;
1005 signal (SIGCHLD, SIG_IGN);
1006 signal (SIGHUP, SIG_IGN);
1007 signal (SIGINT, SIG_IGN);
1008 signal (SIGQUIT, SIG_IGN);
1011 if (exit_state < ES_CLOSEALL)
1013 exit_state = ES_CLOSEALL;
1017 UINT n = (UINT) status;
1018 if (exit_state < ES_THREADTERM)
1020 exit_state = ES_THREADTERM;
1021 cygthread::terminate ();
1024 myself->stopsig = 0;
1026 if (exit_state < ES_HUP_PGRP)
1028 exit_state = ES_HUP_PGRP;
1029 /* Kill orphaned children on group leader exit */
1030 if (myself->has_pgid_children && myself->pid == myself->pgid)
1033 si.si_signo = -SIGHUP;
1034 si.si_code = SI_KERNEL;
1035 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1036 myself->pid, myself->pgid);
1037 kill_pgrp (myself->pgid, si);
1041 if (exit_state < ES_HUP_SID)
1043 exit_state = ES_HUP_SID;
1044 /* Kill the foreground process group on session leader exit */
1045 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1047 tty *tp = cygwin_shared->tty[myself->ctty];
1048 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1049 myself->pid, myself->sid);
1051 /* CGF FIXME: This can't be right. */
1052 if (tp->getsid () == myself->sid)
1053 tp->kill_pgrp (SIGHUP);
1062 cygwin_atexit (void (*fn) (void))
1065 dll *d = dlls.find ((void *) _my_tls.retaddr ());
1066 res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
1073 exit_state = ES_EXIT_STARTING;
1080 do_exit (((DWORD) n & 0xff) << 8);
1083 extern "C" void cygwin_stackdump ();
1086 vapi_fatal (const char *fmt, va_list ap)
1089 int n = __small_sprintf (buf, "%P: *** fatal error %s- ", in_forkee ? "in forked process " : "");
1090 __small_vsprintf (buf + n, fmt, ap);
1092 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1097 cygwin_stackdump ();
1098 myself.exit (__api_fatal_exit_val);
1102 api_fatal (const char *fmt, ...)
1107 vapi_fatal (fmt, ap);
1111 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1113 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1115 child_proc_info->type = _CH_WHOOPS;
1119 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1122 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1123 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1125 api_fatal ("%s mismatch detected - %p/%p.\n\
1126 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1127 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1128 and delete all but the most recent version. The most recent version *should*\n\
1129 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1130 installed the cygwin distribution. Rebooting is also suggested if you\n\
1131 are unable to find another cygwin DLL.",
1132 what, magic_version, version);
1137 cygbench (const char *s)
1139 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1140 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());