1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
16 #include "exceptions.h"
25 #include "perprocess.h"
31 #include "child_info_magic.h"
32 #include "perthread.h"
33 #include "shared_info.h"
34 #include "cygwin_version.h"
36 #include "cygthread.h"
40 #define MAX_AT_FILE_LEVEL 10
42 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
44 HANDLE NO_COPY hMainProc = (HANDLE) -1;
45 HANDLE NO_COPY hMainThread;
48 per_thread_vfork NO_COPY vfork_storage;
51 per_thread NO_COPY *threadstuff[] = {
58 bool strip_title_path;
59 bool allow_glob = true;
60 codepage_type current_codepage = ansi_cp;
63 int _declspec(dllexport) __argc;
64 char _declspec(dllexport) **__argv;
66 vfork_save NO_COPY *main_vfork;
69 static int NO_COPY envc;
72 extern "C" void __sinit (_reent *);
74 _cygtls NO_COPY *_main_tls;
76 bool NO_COPY cygwin_finished_initializing;
78 /* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
79 This is subtracted from the signal number prior to shifting the bit.
80 In older versions of cygwin, the signal was used as-is to shift the
81 bit for masking. So, we'll temporarily detect this and set it to zero
82 for programs that are linked using older cygwins. This is just a stopgap
83 measure to allow an orderly transfer to the new, correct sigmask method. */
84 unsigned NO_COPY int signal_shift_subtract = 1;
86 ResourceLocks _reslock NO_COPY;
87 MTinterface _mtinterf;
89 bool NO_COPY _cygwin_testing;
91 char NO_COPY almost_null[1];
95 /* This is an exported copy of environ which can be used by DLLs
96 which use cygwin.dll. */
97 char **__cygwin_environ;
99 /* __progname used in getopt error message */
101 struct per_process __cygwin_user_data =
102 {/* initial_sp */ 0, /* magic_biscuit */ 0,
103 /* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
104 /* dll_major */ CYGWIN_VERSION_DLL_MINOR,
105 /* impure_ptr_ptr */ NULL, /* envptr */ NULL,
106 /* malloc */ malloc, /* free */ free,
107 /* realloc */ realloc,
108 /* fmode_ptr */ NULL, /* main */ NULL, /* ctors */ NULL,
109 /* dtors */ NULL, /* data_start */ NULL, /* data_end */ NULL,
110 /* bss_start */ NULL, /* bss_end */ NULL,
112 /* premain */ {NULL, NULL, NULL, NULL},
114 /* unused */ {0, 0, 0, 0, 0, 0, 0},
117 /* api_major */ CYGWIN_VERSION_API_MAJOR,
118 /* api_minor */ CYGWIN_VERSION_API_MINOR,
119 /* unused2 */ {0, 0, 0, 0, 0},
120 /* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf,
121 /* impure_ptr */ _GLOBAL_REENT,
123 bool ignore_case_with_glob;
124 int __declspec (dllexport) _check_for_executable = true;
131 char title_buf[TITLESIZE + 1];
134 do_global_dtors (void)
136 if (user_data->dtors)
138 void (**pfunc)() = user_data->dtors;
144 static void __stdcall
145 do_global_ctors (void (**in_pfunc)(), int force)
147 if (!force && user_data->forkee)
148 return; // inherit constructed stuff from parent pid
150 /* Run ctors backwards, so skip the first entry and find how many
151 there are, then run them. */
153 void (**pfunc) () = in_pfunc;
157 while (--pfunc > in_pfunc)
162 * Replaces @file in the command line with the contents of the file.
163 * There may be multiple @file's in a single command line
164 * A \@file is replaced with @file so that echo \@foo would print
165 * @foo and not the contents of foo.
167 static bool __stdcall
168 insert_file (char *name, char *&cmd)
173 f = CreateFile (name + 1,
174 GENERIC_READ, /* open for reading */
175 FILE_SHARE_READ, /* share for reading */
176 &sec_none_nih, /* no security */
177 OPEN_EXISTING, /* existing file only */
178 FILE_ATTRIBUTE_NORMAL, /* normal file */
179 NULL); /* no attr. template */
181 if (f == INVALID_HANDLE_VALUE)
183 debug_printf ("couldn't open file '%s', %E", name);
187 /* This only supports files up to about 4 billion bytes in
188 size. I am making the bold assumption that this is big
189 enough for this feature */
190 size = GetFileSize (f, NULL);
191 if (size == 0xFFFFFFFF)
193 debug_printf ("couldn't get file size for '%s', %E", name);
197 int new_size = strlen (cmd) + size + 2;
198 char *tmp = (char *) malloc (new_size);
201 debug_printf ("malloc failed, %E");
205 /* realloc passed as it should */
208 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
210 if (!rf_result || (rf_read != size))
212 debug_printf ("ReadFile failed, %E");
217 strcpy (tmp + size, cmd);
226 return ch == '"' || ch == '\'';
229 /* Step over a run of characters delimited by quotes */
230 static /*__inline*/ char *
231 quoted (char *cmd, int winshell)
239 strcpy (cmd, cmd + 1);
240 if (*(p = strechr (cmd, quote)))
245 const char *s = quote == '\'' ? "'" : "\\\"";
246 /* This must have been run from a Windows shell, so preserve
247 quotes for globify to play with later. */
248 while (*cmd && *++cmd)
249 if ((p = strpbrk (cmd, s)) == NULL)
251 cmd = strchr (cmd, '\0'); // no closing quote
256 else if (quote == '"' && p[1] == '"')
259 cmd = ++p; // a quoted quote
263 cmd = p + 1; // point to after end
269 /* Perform a glob on word if it contains wildcard characters.
270 Also quote every character between quotes to force glob to
271 treat the characters literally. */
273 globify (char *word, char **&argv, int &argc, int &argvlen)
275 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
280 int dos_spec = isdrive (word);
281 if (!dos_spec && isquote (*word) && word[1] && word[2])
282 dos_spec = isdrive (word + 1);
284 /* We'll need more space if there are quoting characters in
285 word. If that is the case, doubling the size of the
286 string should provide more than enough space. */
287 if (strpbrk (word, "'\""))
289 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
291 /* Fill pattern with characters from word, quoting any
292 characters found within quotes. */
293 for (p = pattern, s = word; *s != '\000'; s++, p++)
296 if (dos_spec && *s == '\\')
303 while (*++s && *s != quote)
305 if (dos_spec || *s != '\\')
307 else if (s[1] == quote || s[1] == '\\')
323 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
324 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
327 /* Allocate enough space in argv for the matched filenames. */
329 if ((argc += gl.gl_pathc) > argvlen)
332 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
335 /* Copy the matched filenames to argv. */
336 char **gv = gl.gl_pathv;
337 char **av = argv + n;
340 debug_printf ("argv[%d] = '%s'", n++, *gv);
344 /* Clean up after glob. */
349 /* Build argv, argc from string passed from Windows. */
351 static void __stdcall
352 build_argv (char *cmd, char **&argv, int &argc, int winshell)
355 int nesting = 0; // monitor "nesting" from insert_file
361 /* Scan command line until there is nothing left. */
371 /* Found the beginning of an argument. */
373 char *sawquote = NULL;
376 if (*cmd != '"' && (!winshell || *cmd != '\''))
377 cmd++; // Skip over this character
379 /* Skip over characters until the closing quote */
382 cmd = quoted (cmd, winshell && argc > 0);
384 if (issep (*cmd)) // End of argument if space
388 *cmd++ = '\0'; // Terminate `word'
390 /* Possibly look for @file construction assuming that this isn't
391 the very first argument and the @ wasn't quoted */
392 if (argc && sawquote != word && *word == '@')
394 if (++nesting > MAX_AT_FILE_LEVEL)
395 api_fatal ("Too many levels of nesting for %s", word);
396 if (insert_file (word, cmd))
397 continue; // There's new stuff in cmd now
400 /* See if we need to allocate more space for argv */
404 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
407 /* Add word to argv file after (optional) wildcard expansion. */
408 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
410 debug_printf ("argv[%d] = '%s'", argc, word);
417 debug_printf ("argc %d", argc);
420 /* sanity and sync check */
422 check_sanity_and_sync (per_process *p)
424 /* Sanity check to make sure developers didn't change the per_process */
425 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
426 /* about changing it]. */
427 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
429 api_fatal ("per_process sanity check failed");
432 /* Make sure that the app and the dll are in sync. */
434 /* Complain if older than last incompatible change */
435 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
436 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
437 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
439 /* magic_biscuit != 0 if using the old style version numbering scheme. */
440 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
441 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
442 p->magic_biscuit, SIZEOF_PER_PROCESS);
444 /* Complain if incompatible API changes made */
445 if (p->api_major > cygwin_version.api_major)
446 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
447 p->api_major, cygwin_version.api_major);
449 if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p->dll_major, p->dll_minor) <=
450 CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK)
451 signal_shift_subtract = 0;
454 child_info NO_COPY *child_proc_info = NULL;
455 static MEMORY_BASIC_INFORMATION NO_COPY sm;
457 #define CYGWIN_GUARD ((wincap.has_page_guard ()) ? \
458 PAGE_EXECUTE_READWRITE|PAGE_GUARD : PAGE_NOACCESS)
461 alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
463 void *new_stack_pointer;
464 MEMORY_BASIC_INFORMATION m;
467 LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;
470 if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)
473 newlen = (LPBYTE) ci->stackbottom - (LPBYTE) curbot;
478 newbase = ci->stacktop;
479 newlen = (DWORD) ci->stackbottom - (DWORD) ci->stacktop;
482 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
483 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
484 ci->stacktop, ci->stackbottom);
486 new_stack_pointer = (void *) ((LPBYTE) ci->stackbottom - ci->stacksize);
488 if (!VirtualAlloc (new_stack_pointer, ci->stacksize, MEM_COMMIT,
489 PAGE_EXECUTE_READWRITE))
490 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
491 new_stack_pointer, ci->stacksize);
492 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
493 api_fatal ("fork: couldn't get new stack info, %E");
496 m.BaseAddress = (LPVOID) ((DWORD) m.BaseAddress - 1);
497 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
499 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
502 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
503 api_fatal ("fork: couldn't get new stack info, %E");
504 ci->stacktop = m.BaseAddress;
508 /* extend the stack prior to fork longjmp */
511 alloc_stack (child_info_fork *ci)
513 /* FIXME: adding 16384 seems to avoid a stack copy problem during
514 fork on Win95, but I don't know exactly why yet. DJ */
515 volatile char b[ci->stacksize + 16384];
517 if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
518 api_fatal ("fork: couldn't get stack info, %E");
520 if (sm.AllocationBase == ci->stacktop)
523 alloc_stack_hard_way (ci, b + sizeof (b) - 1);
532 debug_printf ("break here");
539 char buf[CYG_MAX_PATH + 1];
540 if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
546 if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
548 DWORD ms = atoi (buf);
550 len = GetModuleFileName (NULL, buf, CYG_MAX_PATH);
551 console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
559 if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
561 char buf1[CYG_MAX_PATH + 1];
562 len = GetModuleFileName (NULL, buf1, CYG_MAX_PATH);
565 char *p = strchr (buf, ':');
567 p = (char *) "gdb.exe -nw";
570 if (strstr (buf1, buf))
572 error_start_init (p);
574 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
589 char zeros[sizeof (child_proc_info->zero)] = {0};
591 init_console_handler ();
592 init_global_security ();
593 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
594 GetCurrentProcess (), &hMainProc, 0, FALSE,
595 DUPLICATE_SAME_ACCESS))
596 hMainProc = GetCurrentProcess ();
598 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
599 &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
601 (void) SetErrorMode (SEM_FAILCRITICALERRORS);
604 GetStartupInfo (&si);
605 child_proc_info = (child_info *) si.lpReserved2;
607 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !child_proc_info
608 || memcmp (child_proc_info->zero, zeros,
609 sizeof (child_proc_info->zero)) != 0)
610 child_proc_info = NULL;
613 if ((child_proc_info->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
614 multiple_cygwin_problem ("proc", child_proc_info->intro, 0);
615 else if (child_proc_info->intro == PROC_MAGIC_GENERIC
616 && child_proc_info->magic != CHILD_INFO_MAGIC)
617 multiple_cygwin_problem ("proc", child_proc_info->magic,
619 else if (child_proc_info->cygheap != (void *) &_cygheap_start)
620 multiple_cygwin_problem ("cygheap", (DWORD) child_proc_info->cygheap,
621 (DWORD) &_cygheap_start);
622 unsigned should_be_cb = 0;
623 switch (child_proc_info->type)
626 user_data->forkee = true;
627 should_be_cb = sizeof (child_info_fork);
632 should_be_cb = sizeof (child_info);
633 if (should_be_cb != child_proc_info->cb)
634 multiple_cygwin_problem ("proc size", child_proc_info->cb, should_be_cb);
635 else if (sizeof (fhandler_union) != child_proc_info->fhandler_union_cb)
636 multiple_cygwin_problem ("fhandler size", child_proc_info->fhandler_union_cb, sizeof (fhandler_union));
639 cygwin_user_h = child_proc_info->user_h;
643 system_printf ("unknown exec type %d", child_proc_info->type);
644 /* intentionally fall through */
646 child_proc_info = NULL;
652 do_global_ctors (&__CTOR_LIST__, 1);
655 if (!child_proc_info)
659 bool close_ppid_handle = false;
660 bool close_hexec_proc = false;
661 switch (child_proc_info->type)
664 alloc_stack (fork_info);
665 cygheap_fixup_in_child (false);
668 close_ppid_handle = !!child_proc_info->pppid_handle;
671 /* Have to delay closes until after cygheap is setup */
672 close_hexec_proc = !!spawn_info->hexec_proc;
673 close_ppid_handle = !!child_proc_info->pppid_handle;
676 hexec_proc = spawn_info->hexec_proc;
679 cygheap_fixup_in_child (true);
681 if (!spawn_info->moreinfo->myself_pinfo ||
682 !DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
683 hMainProc, &h, 0, FALSE,
684 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
687 __argc = spawn_info->moreinfo->argc;
688 __argv = spawn_info->moreinfo->argv;
689 envp = spawn_info->moreinfo->envp;
690 envc = spawn_info->moreinfo->envc;
691 cygheap->fdtab.fixup_after_exec ();
692 signal_fixup_after_exec ();
693 if (spawn_info->moreinfo->old_title)
695 old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
696 cfree (spawn_info->moreinfo->old_title);
700 if (close_hexec_proc)
701 CloseHandle (spawn_info->hexec_proc);
702 if (close_ppid_handle)
703 CloseHandle (child_proc_info->pppid_handle);
708 /* Initialize events */
711 cygheap->cwd.init ();
714 /* Take over from libc's crt0.o and start the application. Note the
715 various special cases when Cygwin DLL is being runtime loaded (as
716 opposed to being link-time loaded by Cygwin apps) from a non
717 cygwin app via LoadLibrary. */
721 /* According to onno@stack.urc.tue.nl, the exception handler record must
723 /* FIXME: Verify forked children get their exception handler set up ok. */
724 exception_list cygwin_except_entry;
726 check_sanity_and_sync (user_data);
729 /* Initialize SIGSEGV handling, etc. */
730 init_exceptions (&cygwin_except_entry);
732 user_data->resourcelocks->Init ();
733 user_data->threadinterface->Init ();
734 ProtectHandle (hMainProc);
735 ProtectHandle (hMainThread);
737 /* Initialize pthread mainthread when not forked and it is safe to call new,
738 otherwise it is reinitalized in fixup_after_fork */
739 if (!user_data->forkee)
740 pthread::init_mainthread ();
743 strace.microseconds ();
746 /* Initialize debug muto, if DLL is built with --enable-debugging.
747 Need to do this before any helper threads start. */
751 cygheap->fdtab.vfork_child_fixup ();
752 main_vfork = vfork_storage.create ();
755 cygbench ("pre-forkee");
756 if (user_data->forkee)
758 /* If we've played with the stack, stacksize != 0. That means that
759 fork() was invoked from other than the main thread. Make sure that
760 frame pointer is referencing the new stack so that the OS knows what
761 to do when it needs to increase the size of the stack.
763 NOTE: Don't do anything that involves the stack until you've completed
765 if (fork_info->stacksize)
767 _tlsbase = (char *) fork_info->stackbottom;
768 _tlstop = (char *) fork_info->stacktop;
770 longjmp (fork_info->jmp, true);
775 extern void fork_init ();
780 /* Initialize our process table entry. */
781 pinfo_init (envp, envc);
783 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
784 old_title = title_buf;
786 /* Allocate cygheap->fdtab */
789 /* Initialize user info. */
792 /* Initialize signal/subprocess handling. */
795 /* Connect to tty. */
800 char *line = GetCommandLineA ();
801 line = strcpy ((char *) alloca (strlen (line) + 1), line);
803 if (current_codepage == oem_cp)
804 CharToOemA (line, line);
806 /* Scan the command line and build argv. Expand wildcards if not
807 called from another cygwin process. */
808 build_argv (line, __argv, __argc,
809 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
811 /* Convert argv[0] to posix rules if it's currently blatantly
813 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
815 char *new_argv0 = (char *) malloc (CYG_MAX_PATH);
816 cygwin_conv_to_posix_path (__argv[0], new_argv0);
817 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
821 __argc_safe = __argc;
822 if (user_data->premain[0])
823 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
824 user_data->premain[i] (__argc, __argv, user_data);
826 /* Set up standard fds in file descriptor table. */
827 cygheap->fdtab.stdio_init ();
829 /* Set up __progname for getopt error call. */
830 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
833 __progname = __argv[0];
836 char *cp = strchr (__progname, '\0') - 4;
837 if (cp > __progname && strcasematch (cp, ".exe"))
841 /* Set new console title if appropriate. */
843 if (display_title && !dynamically_loaded)
845 char *cp = __progname;
846 if (strip_title_path)
847 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
850 set_console_title (cp);
853 cygwin_finished_initializing = true;
854 /* Call init of loaded dlls. */
857 /* Execute any specified "premain" functions */
858 if (user_data->premain[PREMAIN_LEN / 2])
859 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
860 user_data->premain[i] (__argc, __argv, user_data);
862 debug_printf ("user_data->main %p", user_data->main);
864 if (dynamically_loaded)
870 /* Disable case-insensitive globbing */
871 ignore_case_with_glob = false;
877 cygbench (__progname);
879 /* Flush signals and ensure that signal thread is up and running. Can't
880 do this for noncygwin case since the signal thread is blocked due to
881 LoadLibrary serialization. */
882 wait_for_sigthread ();
884 exit (user_data->main (__argc, __argv, *user_data->envptr));
888 initialize_main_tls (char *padding)
892 _main_tls = &_my_tls;
893 _main_tls->init_thread (padding, NULL);
895 return &_main_tls->local_clib;
898 /* Wrap the real one, otherwise gdb gets confused about
899 two symbols with the same name, but different addresses.
901 UPTR is a pointer to global data that lives on the libc side of the
902 line [if one distinguishes the application from the dll]. */
904 extern "C" void __stdcall
907 extern HANDLE sync_startup;
908 extern unsigned threadfunc_ix;
911 else if (!sync_startup)
912 system_printf ("internal error: sync_startup not called at start. Expect signal problems.");
915 (void) WaitForSingleObject (sync_startup, INFINITE);
916 CloseHandle (sync_startup);
920 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
922 main_environ = user_data->envptr;
923 *main_environ = NULL;
925 char padding[CYGTLS_PADSIZE];
926 _impure_ptr = _GLOBAL_REENT;
927 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
928 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
929 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
930 _impure_ptr->_current_locale = "C";
932 if (child_proc_info && child_proc_info->type == _PROC_FORK)
933 user_data->forkee = true;
935 __sinit (_impure_ptr);
937 initialize_main_tls (padding);
938 dll_crt0_1 (padding);
942 dll_crt0 (per_process *uptr)
944 /* Set the local copy of the pointer into the user space. */
945 if (uptr && uptr != user_data)
947 memcpy (user_data, uptr, per_process_overwrite);
948 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
953 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll */
960 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
961 GetCurrentProcess (), &hMainProc, 0, FALSE,
962 DUPLICATE_SAME_ACCESS))
963 hMainProc = GetCurrentProcess ();
965 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
966 &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
967 user_data->magic_biscuit = sizeof (per_process);
969 user_data->envptr = &envp;
970 user_data->fmode_ptr = &_fmode;
978 do_global_ctors (user_data->ctors, false);
979 atexit (do_global_dtors);
982 exit_states NO_COPY exit_state;
983 extern CRITICAL_SECTION exit_lock;
988 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
991 vfork_save *vf = vfork_storage.val ();
992 if (vf != NULL && vf->pid < 0)
994 exit_state = ES_NOT_EXITING;
995 vf->restore_exit (status);
999 EnterCriticalSection (&exit_lock);
1000 muto::set_exiting_thread ();
1001 if (exit_state < ES_EVENTS_TERMINATE)
1003 exit_state = ES_EVENTS_TERMINATE;
1004 events_terminate ();
1007 UINT n = (UINT) status;
1008 if (exit_state < ES_THREADTERM)
1010 exit_state = ES_THREADTERM;
1011 cygthread::terminate ();
1014 if (exit_state < ES_SIGNAL)
1016 exit_state = ES_SIGNAL;
1017 if (!(n & EXIT_REPARENTING))
1019 signal (SIGCHLD, SIG_IGN);
1020 signal (SIGHUP, SIG_IGN);
1021 signal (SIGINT, SIG_IGN);
1022 signal (SIGQUIT, SIG_IGN);
1026 if (exit_state < ES_CLOSEALL)
1028 exit_state = ES_CLOSEALL;
1032 if (exit_state < ES_SIGPROCTERMINATE)
1034 exit_state = ES_SIGPROCTERMINATE;
1035 sigproc_terminate ();
1038 myself->stopsig = 0;
1039 if (exit_state < ES_TITLE)
1041 exit_state = ES_TITLE;
1042 /* restore console title */
1043 if (old_title && display_title)
1044 set_console_title (old_title);
1047 if (exit_state < ES_HUP_PGRP)
1049 exit_state = ES_HUP_PGRP;
1050 /* Kill orphaned children on group leader exit */
1051 if (myself->has_pgid_children && myself->pid == myself->pgid)
1054 si.si_signo = -SIGHUP;
1055 si.si_code = SI_KERNEL;
1056 si.si_pid = si.si_uid = si.si_errno = 0;
1057 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1058 myself->pid, myself->pgid);
1059 kill_pgrp (myself->pgid, si);
1063 if (exit_state < ES_HUP_SID)
1065 exit_state = ES_HUP_SID;
1066 /* Kill the foreground process group on session leader exit */
1067 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1069 tty *tp = cygwin_shared->tty[myself->ctty];
1070 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1071 myself->pid, myself->sid);
1073 /* CGF FIXME: This can't be right. */
1074 if (tp->getsid () == myself->sid)
1075 tp->kill_pgrp (SIGHUP);
1080 if (exit_state < ES_TTY_TERMINATE)
1082 exit_state = ES_TTY_TERMINATE;
1086 minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
1090 static muto *atexit_lock;
1093 cygwin_atexit (void (*function)(void))
1097 new_muto (atexit_lock);
1098 atexit_lock->acquire ();
1099 res = atexit (function);
1100 atexit_lock->release ();
1108 atexit_lock->acquire ();
1115 do_exit ((DWORD) n & 0xffff);
1119 __api_fatal (const char *fmt, ...)
1125 int n = __small_sprintf (buf, "%P (%u): *** ", cygwin_pid (GetCurrentProcessId ()));
1126 __small_vsprintf (buf + n, fmt, ap);
1129 int len = strlen (buf);
1131 (void) WriteFile (GetStdHandle (STD_ERROR_HANDLE), buf, len, &done, 0);
1133 /* Make sure that the message shows up on the screen, too, since this is
1135 if (GetFileType (GetStdHandle (STD_ERROR_HANDLE)) != FILE_TYPE_CHAR)
1137 HANDLE h = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
1138 FILE_SHARE_WRITE | FILE_SHARE_WRITE,
1139 &sec_none, OPEN_EXISTING, 0, 0);
1140 if (h != INVALID_HANDLE_VALUE)
1141 (void) WriteFile (h, buf, len, &done, 0);
1144 /* We are going down without mercy. Make sure we reset
1145 our process_state. */
1146 sigproc_terminate ();
1148 (void) try_to_debug ();
1154 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1156 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1158 child_proc_info->type = _PROC_WHOOPS;
1163 if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf, sizeof (buf)))
1166 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1167 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1169 api_fatal ("%s version mismatch detected - %p/%p.\n\
1170 You have multiple copies of cygwin1.dll on your system.\n\
1171 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1172 and delete all but the most recent version. The most recent version *should*\n\
1173 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1174 installed the cygwin distribution.", what, magic_version, version);
1179 cygbench (const char *s)
1182 if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))
1183 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());