1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
7 This file is part of Cygwin.
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
14 #include "miscfuncs.h"
25 #include "perprocess.h"
30 #include "child_info_magic.h"
32 #include "shared_info.h"
33 #include "cygwin_version.h"
38 #define MAX_AT_FILE_LEVEL 10
40 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
43 extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
44 extern "C" void __sinit (_reent *);
46 static int NO_COPY envc;
47 static char NO_COPY **envp;
49 static char title_buf[TITLESIZE + 1];
54 void (**pfunc) () = user_data->dtors;
57 user_data->dtors = NULL;
64 do_global_ctors (void (**in_pfunc)(), int force)
66 if (!force && in_forkee)
67 return; // inherit constructed stuff from parent pid
69 /* Run ctors backwards, so skip the first entry and find how many
70 there are, then run them. */
72 void (**pfunc) () = in_pfunc;
76 while (--pfunc > in_pfunc)
81 * Replaces @file in the command line with the contents of the file.
82 * There may be multiple @file's in a single command line
83 * A \@file is replaced with @file so that echo \@foo would print
84 * @foo and not the contents of foo.
87 insert_file (char *name, char *&cmd)
93 PWCHAR wname = tp.w_get ();
94 sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
95 f = CreateFileW (wname,
96 GENERIC_READ, /* open for reading */
97 FILE_SHARE_READ, /* share for reading */
98 &sec_none_nih, /* default security */
99 OPEN_EXISTING, /* existing file only */
100 FILE_ATTRIBUTE_NORMAL,/* normal file */
101 NULL); /* no attr. template */
103 if (f == INVALID_HANDLE_VALUE)
105 debug_printf ("couldn't open file '%s', %E", name);
109 /* This only supports files up to about 4 billion bytes in
110 size. I am making the bold assumption that this is big
111 enough for this feature */
112 size = GetFileSize (f, NULL);
113 if (size == 0xFFFFFFFF)
115 debug_printf ("couldn't get file size for '%s', %E", name);
119 int new_size = strlen (cmd) + size + 2;
120 char *tmp = (char *) malloc (new_size);
123 debug_printf ("malloc failed, %E");
127 /* realloc passed as it should */
130 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
132 if (!rf_result || (rf_read != size))
134 debug_printf ("ReadFile failed, %E");
139 strcpy (tmp + size, cmd);
148 return ch == '"' || ch == '\'';
151 /* Step over a run of characters delimited by quotes */
152 static /*__inline*/ char *
153 quoted (char *cmd, int winshell)
161 strcpy (cmd, cmd + 1);
162 if (*(p = strechr (cmd, quote)))
167 const char *s = quote == '\'' ? "'" : "\\\"";
168 /* This must have been run from a Windows shell, so preserve
169 quotes for globify to play with later. */
170 while (*cmd && *++cmd)
171 if ((p = strpbrk (cmd, s)) == NULL)
173 cmd = strchr (cmd, '\0'); // no closing quote
178 else if (quote == '"' && p[1] == '"')
181 cmd = ++p; // a quoted quote
185 cmd = p + 1; // point to after end
191 /* Perform a glob on word if it contains wildcard characters.
192 Also quote every character between quotes to force glob to
193 treat the characters literally. */
195 globify (char *word, char **&argv, int &argc, int &argvlen)
197 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
202 int dos_spec = isdrive (word);
203 if (!dos_spec && isquote (*word) && word[1] && word[2])
204 dos_spec = isdrive (word + 1);
206 /* We'll need more space if there are quoting characters in
207 word. If that is the case, doubling the size of the
208 string should provide more than enough space. */
209 if (strpbrk (word, "'\""))
211 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
213 /* Fill pattern with characters from word, quoting any
214 characters found within quotes. */
215 for (p = pattern, s = word; *s != '\000'; s++, p++)
218 if (dos_spec && *s == '\\')
225 while (*++s && *s != quote)
227 if (dos_spec || *s != '\\')
229 else if (s[1] == quote || s[1] == '\\')
232 size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
233 if (cnt <= 1 || cnt == (size_t)-1)
253 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
254 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
257 /* Allocate enough space in argv for the matched filenames. */
259 if ((argc += gl.gl_pathc) > argvlen)
262 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
265 /* Copy the matched filenames to argv. */
266 char **gv = gl.gl_pathv;
267 char **av = argv + n;
270 debug_printf ("argv[%d] = '%s'", n++, *gv);
274 /* Clean up after glob. */
279 /* Build argv, argc from string passed from Windows. */
281 static void __stdcall
282 build_argv (char *cmd, char **&argv, int &argc, int winshell)
285 int nesting = 0; // monitor "nesting" from insert_file
291 /* Scan command line until there is nothing left. */
301 /* Found the beginning of an argument. */
303 char *sawquote = NULL;
306 if (*cmd != '"' && (!winshell || *cmd != '\''))
307 cmd++; // Skip over this character
309 /* Skip over characters until the closing quote */
312 cmd = quoted (cmd, winshell && argc > 0);
314 if (issep (*cmd)) // End of argument if space
318 *cmd++ = '\0'; // Terminate `word'
320 /* Possibly look for @file construction assuming that this isn't
321 the very first argument and the @ wasn't quoted */
322 if (argc && sawquote != word && *word == '@')
324 if (++nesting > MAX_AT_FILE_LEVEL)
325 api_fatal ("Too many levels of nesting for %s", word);
326 if (insert_file (word, cmd))
327 continue; // There's new stuff in cmd now
330 /* See if we need to allocate more space for argv */
334 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
337 /* Add word to argv file after (optional) wildcard expansion. */
338 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
340 debug_printf ("argv[%d] = '%s'", argc, word);
347 debug_printf ("argc %d", argc);
350 /* sanity and sync check */
352 check_sanity_and_sync (per_process *p)
354 /* Sanity check to make sure developers didn't change the per_process */
355 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
356 /* about changing it]. */
357 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
358 api_fatal ("per_process sanity check failed");
360 /* Make sure that the app and the dll are in sync. */
362 /* Complain if older than last incompatible change */
363 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
364 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
365 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
367 /* magic_biscuit != 0 if using the old style version numbering scheme. */
368 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
369 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
370 p->magic_biscuit, SIZEOF_PER_PROCESS);
372 /* Complain if incompatible API changes made */
373 if (p->api_major > cygwin_version.api_major)
374 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
375 p->api_major, cygwin_version.api_major);
378 child_info NO_COPY *child_proc_info = NULL;
380 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
383 child_info_fork::alloc_stack_hard_way (volatile char *b)
385 void *new_stack_pointer;
386 MEMORY_BASIC_INFORMATION m;
391 if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
392 api_fatal ("fork: couldn't get stack info, %E");
394 LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
396 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
399 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
404 newbase = (LPBYTE) stacktop - (128 * 1024);
405 newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
409 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
410 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
411 stacktop, stackbottom);
412 new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
413 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
414 PAGE_EXECUTE_READWRITE))
415 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
416 new_stack_pointer, stacksize);
417 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
418 api_fatal ("fork: couldn't get new stack info, %E");
422 m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
423 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
425 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
428 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
429 api_fatal ("fork: couldn't get new stack info, %E");
430 stacktop = m.BaseAddress;
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))
477 char buf[NT_MAX_PATH];
480 if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
482 DWORD ms = atoi (buf);
483 console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
485 if (!strace.active () && !dynamically_loaded)
488 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
490 char buf1[NT_MAX_PATH];
491 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
494 char *p = strpbrk (buf, ":=");
496 p = (char *) "gdb.exe -nw";
499 if (strstr (buf1, buf))
501 error_start_init (p);
503 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
512 get_cygwin_startup_info ()
516 GetStartupInfo (&si);
517 child_info *res = (child_info *) si.lpReserved2;
519 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
520 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
524 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
525 multiple_cygwin_problem ("proc intro", res->intro, 0);
526 else if (res->cygheap != (void *) &_cygheap_start)
527 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
528 (DWORD) &_cygheap_start);
530 unsigned should_be_cb = 0;
535 should_be_cb = sizeof (child_info_fork);
540 should_be_cb = sizeof (child_info_spawn);
541 if (should_be_cb != res->cb)
542 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
543 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
544 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
545 if (res->isstraced ())
548 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
549 low_priority_sleep (0);
554 system_printf ("unknown exec type %d", res->type);
555 /* intentionally fall through */
565 #define dll_data_start &_data_start__
566 #define dll_data_end &_data_end__
567 #define dll_bss_start &_bss_start__
568 #define dll_bss_end &_bss_end__
571 child_info_fork::handle_fork ()
573 cygheap_fixup_in_child (false);
575 myself.thisproc (NULL);
576 myself->uid = cygheap->user.real_uid;
577 myself->gid = cygheap->user.real_gid;
579 child_copy (parent, false,
580 "dll data", dll_data_start, dll_data_end,
581 "dll bss", dll_bss_start, dll_bss_end,
582 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
584 /* step 2 now that the dll has its heap filled in, we can fill in the
585 user's data and bss since user_data is now filled out. */
586 child_copy (parent, false,
587 "data", user_data->data_start, user_data->data_end,
588 "bss", user_data->bss_start, user_data->bss_end,
591 if (fixup_mmaps_after_fork (parent))
592 api_fatal ("recreate_mmaps_after_fork_failed");
596 child_info_spawn::handle_spawn ()
598 extern void fixup_lockf_after_exec ();
600 cygheap_fixup_in_child (true);
602 if (!moreinfo->myself_pinfo ||
603 !DuplicateHandle (hMainProc, moreinfo->myself_pinfo, hMainProc, &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 ();
621 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
622 handles might get confused. */
623 CloseHandle (child_proc_info->parent);
624 child_proc_info->parent = NULL;
626 signal_fixup_after_exec ();
627 if (moreinfo->old_title)
629 old_title = strcpy (title_buf, moreinfo->old_title);
630 cfree (moreinfo->old_title);
632 fixup_lockf_after_exec ();
636 /* Setting the TS-aware flag in the application's PE header is sufficient.
637 Just keep this in as a reminder. */
639 static DEP_SYSTEM_POLICY_TYPE dep_system_policy = (DEP_SYSTEM_POLICY_TYPE) -1;
647 if (dep_system_policy < 0)
649 dep_system_policy = GetSystemDEPPolicy ();
650 debug_printf ("DEP System Policy: %d", (int) dep_system_policy);
652 if (dep_system_policy < OptIn)
654 if (!GetProcessDEPPolicy (hMainProc, &ppolicy, &perm))
656 debug_printf ("GetProcessDEPPolicy: %E");
659 debug_printf ("DEP Process Policy: %d (permanent = %d)", ppolicy, perm);
660 if (ppolicy > 0 && !perm && !SetProcessDEPPolicy (0))
661 debug_printf ("SetProcessDEPPolicy: %E");
668 init_global_security ();
671 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
673 /* Initialize signal processing here, early, in the hopes that the creation
674 of a thread early in the process will cause more predictability in memory
675 layout for the main thread. */
676 if (!dynamically_loaded)
679 lock_process::init ();
680 _impure_ptr = _GLOBAL_REENT;
681 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
682 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
683 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
684 _impure_ptr->_current_locale = "C";
685 user_data->impure_ptr = _impure_ptr;
686 user_data->impure_ptr_ptr = &_impure_ptr;
688 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
689 GetCurrentProcess (), &hMainProc, 0, FALSE,
690 DUPLICATE_SAME_ACCESS))
691 hMainProc = GetCurrentProcess ();
693 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
694 &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
696 OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
697 set_cygwin_privileges (hProcToken);
700 do_global_ctors (&__CTOR_LIST__, 1);
703 child_proc_info = get_cygwin_startup_info ();
704 if (!child_proc_info)
708 cygwin_user_h = child_proc_info->user_h;
709 switch (child_proc_info->type)
712 fork_info->handle_fork ();
716 spawn_info->handle_spawn ();
721 user_data->threadinterface->Init ();
725 /* Initialize events */
727 tty_list::init_session ();
730 /* Setting the TS-aware flag in the application's PE header is sufficient.
731 Just keep this in as a reminder. */
733 /* The disable_dep function disables DEP for all Cygwin processes if
734 the process runs on a Windows Server 2008 with Terminal Services
735 installed. This combination (TS+DEP) breaks *some* Cygwin
736 applications. The Terminal Service specific DLL tsappcmp.dll
737 changes the page protection of some pages in the application's text
738 segment from PAGE_EXECUTE_WRITECOPY to PAGE_WRITECOPY for no
739 apparent reason. This occurs before any Cygwin or applicaton code
740 had a chance to run. MS has no explanation for this so far, but is
741 rather busy trying to avoid giving support for this problem (as of
744 Unfortunately disabling DEP seems to have a not negligible
745 performance hit. In the long run, either MS has to fix their
746 problem, or we have to find a better workaround, if any exists.
747 Idle idea: Adding EXECUTE protection to all text segment pages? */
748 if (wincap.ts_has_dep_problem ())
752 debug_printf ("finished dll_crt0_0 initialization");
755 /* Take over from libc's crt0.o and start the application. Note the
756 various special cases when Cygwin DLL is being runtime loaded (as
757 opposed to being link-time loaded by Cygwin apps) from a non
758 cygwin app via LoadLibrary. */
762 if (dynamically_loaded)
764 check_sanity_and_sync (user_data);
766 /* Initialize malloc and then call user_shared_initialize since it relies
767 on a functioning malloc and it's possible that the user's program may
768 have overridden malloc. We only know about that at this stage,
771 user_shared_initialize ();
775 const int n = 2 * 1024 * 1024;
777 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
780 ProtectHandle (hMainProc);
781 ProtectHandle (hMainThread);
783 cygheap->cwd.init ();
785 /* Initialize pthread mainthread when not forked and it is safe to call new,
786 otherwise it is reinitalized in fixup_after_fork */
788 pthread::init_mainthread ();
791 strace.microseconds ();
794 create_signal_arrived (); /* FIXME: move into wait_sig? */
796 /* Initialize debug muto, if DLL is built with --enable-debugging.
797 Need to do this before any helper threads start. */
801 cygheap->fdtab.vfork_child_fixup ();
802 main_vfork = vfork_storage.create ();
805 cygbench ("pre-forkee");
808 /* If we've played with the stack, stacksize != 0. That means that
809 fork() was invoked from other than the main thread. Make sure that
810 frame pointer is referencing the new stack so that the OS knows what
811 to do when it needs to increase the size of the stack.
813 NOTE: Don't do anything that involves the stack until you've completed
815 if (fork_info->stacksize)
817 _tlsbase = (char *) fork_info->stackbottom;
818 _tlstop = (char *) fork_info->stacktop;
819 _my_tls.init_exception_handler (_cygtls::handle_exceptions);
822 longjmp (fork_info->jmp, true);
827 extern void fork_init ();
831 pinfo_init (envp, envc);
833 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
834 old_title = title_buf;
836 /* Allocate cygheap->fdtab */
839 uinfo_init (); /* initialize user info */
841 wait_for_sigthread ();
842 extern DWORD threadfunc_ix;
844 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
846 /* Connect to tty. */
847 tty::init_session ();
851 PWCHAR wline = GetCommandLineW ();
852 size_t size = sys_wcstombs (NULL, 0, wline);
853 char *line = (char *) alloca (size);
854 sys_wcstombs (line, size, wline);
856 /* Scan the command line and build argv. Expand wildcards if not
857 called from another cygwin process. */
858 build_argv (line, __argv, __argc,
859 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
861 /* Convert argv[0] to posix rules if it's currently blatantly
863 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
865 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
866 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
867 new_argv0, NT_MAX_PATH);
868 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
872 __argc_safe = __argc;
873 if (user_data->premain[0])
874 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
875 user_data->premain[i] (__argc, __argv, user_data);
877 /* Set up standard fds in file descriptor table. */
878 cygheap->fdtab.stdio_init ();
880 /* Set up __progname for getopt error call. */
881 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
884 __progname = __argv[0];
887 char *cp = strchr (__progname, '\0') - 4;
888 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
892 /* Set new console title if appropriate. */
894 if (display_title && !dynamically_loaded)
896 char *cp = __progname;
897 if (strip_title_path)
898 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
901 set_console_title (cp);
904 cygwin_finished_initializing = true;
905 /* Call init of loaded dlls. */
908 /* Execute any specified "premain" functions */
909 if (user_data->premain[PREMAIN_LEN / 2])
910 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
911 user_data->premain[i] (__argc, __argv, user_data);
913 debug_printf ("user_data->main %p", user_data->main);
915 if (dynamically_loaded)
921 /* Disable case-insensitive globbing */
922 ignore_case_with_glob = false;
927 cygbench (__progname);
929 /* Flush signals and ensure that signal thread is up and running. Can't
930 do this for noncygwin case since the signal thread is blocked due to
931 LoadLibrary serialization. */
933 /* Reset current locale to "C" per POSIX */
934 _setlocale_r (_GLOBAL_REENT, LC_CTYPE, "C");
936 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
938 .global __cygwin_exit_return \n\
939 __cygwin_exit_return: \n\
943 extern "C" void __stdcall
946 main_environ = user_data->envptr;
948 fork_info->alloc_stack ();
950 __sinit (_impure_ptr);
952 _main_tls = &_my_tls;
953 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
957 dll_crt0 (per_process *uptr)
959 /* Set the local copy of the pointer into the user space. */
960 if (!in_forkee && uptr && uptr != user_data)
962 memcpy (user_data, uptr, per_process_overwrite);
963 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
968 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
969 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
970 calling this function, and that storage must not be overwritten until you
971 unload cygwin1.dll, as it is used for _my_tls. It is best to load
972 cygwin1.dll before spawning any additional threads in your process.
974 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
975 from MSVC and non-cygwin MinGW applications. */
982 user_data->magic_biscuit = sizeof (per_process);
984 user_data->envptr = &envp;
985 user_data->fmode_ptr = &_fmode;
993 do_global_ctors (user_data->ctors, false);
994 atexit (do_global_dtors);
1000 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1003 vfork_save *vf = vfork_storage.val ();
1004 if (vf != NULL && vf->pid < 0)
1006 exit_state = ES_NOT_EXITING;
1007 vf->restore_exit (status);
1011 lock_process until_exit (true);
1013 if (exit_state < ES_GLOBAL_DTORS)
1015 exit_state = ES_GLOBAL_DTORS;
1016 dll_global_dtors ();
1019 if (exit_state < ES_EVENTS_TERMINATE)
1021 exit_state = ES_EVENTS_TERMINATE;
1022 events_terminate ();
1025 UINT n = (UINT) status;
1026 if (exit_state < ES_THREADTERM)
1028 exit_state = ES_THREADTERM;
1029 cygthread::terminate ();
1032 if (exit_state < ES_SIGNAL)
1034 exit_state = ES_SIGNAL;
1035 signal (SIGCHLD, SIG_IGN);
1036 signal (SIGHUP, SIG_IGN);
1037 signal (SIGINT, SIG_IGN);
1038 signal (SIGQUIT, SIG_IGN);
1041 if (exit_state < ES_CLOSEALL)
1043 exit_state = ES_CLOSEALL;
1047 myself->stopsig = 0;
1049 if (exit_state < ES_HUP_PGRP)
1051 exit_state = ES_HUP_PGRP;
1052 /* Kill orphaned children on group leader exit */
1053 if (myself->has_pgid_children && myself->pid == myself->pgid)
1056 si.si_signo = -SIGHUP;
1057 si.si_code = SI_KERNEL;
1058 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1059 myself->pid, myself->pgid);
1060 kill_pgrp (myself->pgid, si);
1064 if (exit_state < ES_HUP_SID)
1066 exit_state = ES_HUP_SID;
1067 /* Kill the foreground process group on session leader exit */
1068 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1070 tty *tp = cygwin_shared->tty[myself->ctty];
1071 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1072 myself->pid, myself->sid);
1074 /* CGF FIXME: This can't be right. */
1075 if (tp->getsid () == myself->sid)
1076 tp->kill_pgrp (SIGHUP);
1081 if (exit_state < ES_TITLE)
1083 exit_state = ES_TITLE;
1084 /* restore console title */
1085 if (old_title && display_title)
1086 set_console_title (old_title);
1089 if (exit_state < ES_TTY_TERMINATE)
1091 exit_state = ES_TTY_TERMINATE;
1092 cygwin_shared->tty.terminate ();
1098 static NO_COPY muto atexit_lock;
1101 cygwin_atexit (void (*function)(void))
1104 atexit_lock.init ("atexit_lock");
1105 atexit_lock.acquire ();
1106 res = atexit (function);
1107 atexit_lock.release ();
1115 atexit_lock.acquire ();
1122 do_exit (((DWORD) n & 0xff) << 8);
1126 __api_fatal (const char *fmt, ...)
1132 int n = __small_sprintf (buf, "%P: *** fatal error - ");
1133 __small_vsprintf (buf + n, fmt, ap);
1135 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1140 myself.exit (__api_fatal_exit_val);
1144 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1146 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1148 child_proc_info->type = _PROC_WHOOPS;
1152 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1155 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1156 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1158 api_fatal ("%s mismatch detected - %p/%p.\n\
1159 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1160 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1161 and delete all but the most recent version. The most recent version *should*\n\
1162 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1163 installed the cygwin distribution. Rebooting is also suggested if you\n\
1164 are unable to find another cygwin DLL.",
1165 what, magic_version, version);
1170 cygbench (const char *s)
1172 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1173 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());