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];
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_READ, /* 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)
393 void *new_stack_pointer;
394 MEMORY_BASIC_INFORMATION m;
399 if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
400 api_fatal ("fork: couldn't get stack info, %E");
402 LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
404 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
407 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
412 newbase = (LPBYTE) stacktop - (128 * 1024);
413 newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
417 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
418 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
419 stacktop, stackbottom);
420 new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
421 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
422 PAGE_EXECUTE_READWRITE))
423 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
424 new_stack_pointer, stacksize);
425 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
426 api_fatal ("fork: couldn't get new stack info, %E");
430 m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
431 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
433 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
436 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
437 api_fatal ("fork: couldn't get new stack info, %E");
438 stacktop = m.BaseAddress;
442 void *getstack (void *) __attribute__ ((noinline));
444 getstack (volatile char * volatile p)
451 /* extend the stack prior to fork longjmp */
454 child_info_fork::alloc_stack ()
456 volatile char * volatile esp;
457 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
458 if (_tlsbase != stackbottom)
459 alloc_stack_hard_way (esp);
462 char *st = (char *) stacktop - 4096;
463 while (_tlstop >= st)
464 esp = getstack (esp);
472 static int NO_COPY sent_break;
475 debug_printf ("break here");
481 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
485 char buf[NT_MAX_PATH];
488 if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
490 DWORD ms = atoi (buf);
491 console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
493 if (!strace.active () && !dynamically_loaded)
496 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
498 char buf1[NT_MAX_PATH];
499 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
502 char *p = strpbrk (buf, ":=");
504 p = (char *) "gdb.exe -nw";
507 if (strstr (buf1, buf))
509 error_start_init (p);
512 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
521 get_cygwin_startup_info ()
525 GetStartupInfo (&si);
526 child_info *res = (child_info *) si.lpReserved2;
528 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
529 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
533 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
534 multiple_cygwin_problem ("proc intro", res->intro, 0);
535 else if (res->cygheap != (void *) &_cygheap_start)
536 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
537 (DWORD) &_cygheap_start);
539 unsigned should_be_cb = 0;
544 should_be_cb = sizeof (child_info_fork);
549 should_be_cb = sizeof (child_info_spawn);
550 if (should_be_cb != res->cb)
551 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
552 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
553 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
554 if (res->isstraced ())
557 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
558 low_priority_sleep (0);
563 system_printf ("unknown exec type %d", res->type);
564 /* intentionally fall through */
574 #define dll_data_start &_data_start__
575 #define dll_data_end &_data_end__
576 #define dll_bss_start &_bss_start__
577 #define dll_bss_end &_bss_end__
580 child_info_fork::handle_fork ()
582 cygheap_fixup_in_child (false);
584 myself.thisproc (NULL);
585 myself->uid = cygheap->user.real_uid;
586 myself->gid = cygheap->user.real_gid;
588 child_copy (parent, false,
589 "dll data", dll_data_start, dll_data_end,
590 "dll bss", dll_bss_start, dll_bss_end,
591 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
593 /* step 2 now that the dll has its heap filled in, we can fill in the
594 user's data and bss since user_data is now filled out. */
595 child_copy (parent, false,
596 "data", user_data->data_start, user_data->data_end,
597 "bss", user_data->bss_start, user_data->bss_end,
600 if (fixup_mmaps_after_fork (parent))
601 api_fatal ("recreate_mmaps_after_fork_failed");
605 child_info_spawn::handle_spawn ()
607 extern void fixup_lockf_after_exec ();
609 cygheap_fixup_in_child (true);
611 if (!moreinfo->myself_pinfo ||
612 !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
613 GetCurrentProcess (), &h, 0,
614 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
617 __argc = moreinfo->argc;
618 __argv = moreinfo->argv;
619 envp = moreinfo->envp;
620 envc = moreinfo->envc;
621 if (!dynamically_loaded)
622 cygheap->fdtab.fixup_after_exec ();
624 cygheap->fdtab.move_fd (__stdin, 0);
626 cygheap->fdtab.move_fd (__stdout, 1);
627 cygheap->user.groups.clear_supp ();
631 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
632 handles might get confused. */
633 CloseHandle (child_proc_info->parent);
634 child_proc_info->parent = NULL;
636 signal_fixup_after_exec ();
637 if (moreinfo->old_title)
639 old_title = strcpy (title_buf, moreinfo->old_title);
640 cfree (moreinfo->old_title);
642 fixup_lockf_after_exec ();
646 /* Setting the TS-aware flag in the application's PE header is sufficient.
647 Just keep this in as a reminder. */
649 static DEP_SYSTEM_POLICY_TYPE dep_system_policy = (DEP_SYSTEM_POLICY_TYPE) -1;
657 if (dep_system_policy < 0)
659 dep_system_policy = GetSystemDEPPolicy ();
660 debug_printf ("DEP System Policy: %d", (int) dep_system_policy);
662 if (dep_system_policy < OptIn)
664 if (!GetProcessDEPPolicy (GetCurrentProcess (), &ppolicy, &perm))
666 debug_printf ("GetProcessDEPPolicy: %E");
669 debug_printf ("DEP Process Policy: %d (permanent = %d)", ppolicy, perm);
670 if (ppolicy > 0 && !perm && !SetProcessDEPPolicy (0))
671 debug_printf ("SetProcessDEPPolicy: %E");
678 init_global_security ();
681 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
683 /* Initialize signal processing here, early, in the hopes that the creation
684 of a thread early in the process will cause more predictability in memory
685 layout for the main thread. */
686 if (!dynamically_loaded)
689 lock_process::init ();
690 _impure_ptr = _GLOBAL_REENT;
691 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
692 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
693 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
694 _impure_ptr->_current_locale = "C";
695 user_data->impure_ptr = _impure_ptr;
696 user_data->impure_ptr_ptr = &_impure_ptr;
698 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
699 GetCurrentProcess (), &hMainThread,
700 0, false, DUPLICATE_SAME_ACCESS);
702 OpenProcessToken (GetCurrentProcess (), MAXIMUM_ALLOWED, &hProcToken);
703 set_cygwin_privileges (hProcToken);
706 do_global_ctors (&__CTOR_LIST__, 1);
709 child_proc_info = get_cygwin_startup_info ();
710 if (!child_proc_info)
714 cygwin_user_h = child_proc_info->user_h;
715 switch (child_proc_info->type)
718 fork_info->handle_fork ();
722 spawn_info->handle_spawn ();
727 user_data->threadinterface->Init ();
731 /* Initialize events */
733 tty_list::init_session ();
736 /* Setting the TS-aware flag in the application's PE header is sufficient.
737 Just keep this in as a reminder. */
739 /* The disable_dep function disables DEP for all Cygwin processes if
740 the process runs on a Windows Server 2008 with Terminal Services
741 installed. This combination (TS+DEP) breaks *some* Cygwin
742 applications. The Terminal Service specific DLL tsappcmp.dll
743 changes the page protection of some pages in the application's text
744 segment from PAGE_EXECUTE_WRITECOPY to PAGE_WRITECOPY for no
745 apparent reason. This occurs before any Cygwin or applicaton code
746 had a chance to run. MS has no explanation for this so far, but is
747 rather busy trying to avoid giving support for this problem (as of
750 Unfortunately disabling DEP seems to have a not negligible
751 performance hit. In the long run, either MS has to fix their
752 problem, or we have to find a better workaround, if any exists.
753 Idle idea: Adding EXECUTE protection to all text segment pages? */
754 if (wincap.ts_has_dep_problem ())
758 debug_printf ("finished dll_crt0_0 initialization");
761 /* Take over from libc's crt0.o and start the application. Note the
762 various special cases when Cygwin DLL is being runtime loaded (as
763 opposed to being link-time loaded by Cygwin apps) from a non
764 cygwin app via LoadLibrary. */
768 extern void initial_setlocale ();
770 if (dynamically_loaded)
772 check_sanity_and_sync (user_data);
774 /* Initialize malloc and then call user_shared_initialize since it relies
775 on a functioning malloc and it's possible that the user's program may
776 have overridden malloc. We only know about that at this stage,
779 user_shared_initialize ();
783 const int n = 2 * 1024 * 1024;
785 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
788 ProtectHandle (hMainThread);
790 cygheap->cwd.init ();
792 /* Initialize pthread mainthread when not forked and it is safe to call new,
793 otherwise it is reinitalized in fixup_after_fork */
795 pthread::init_mainthread ();
798 strace.microseconds ();
801 create_signal_arrived (); /* FIXME: move into wait_sig? */
803 /* Initialize debug muto, if DLL is built with --enable-debugging.
804 Need to do this before any helper threads start. */
808 cygheap->fdtab.vfork_child_fixup ();
809 main_vfork = vfork_storage.create ();
812 cygbench ("pre-forkee");
815 /* If we've played with the stack, stacksize != 0. That means that
816 fork() was invoked from other than the main thread. Make sure that
817 frame pointer is referencing the new stack so that the OS knows what
818 to do when it needs to increase the size of the stack.
820 NOTE: Don't do anything that involves the stack until you've completed
822 if (fork_info->stacksize)
824 _tlsbase = (char *) fork_info->stackbottom;
825 _tlstop = (char *) fork_info->stacktop;
826 _my_tls.init_exception_handler (_cygtls::handle_exceptions);
829 longjmp (fork_info->jmp, true);
834 extern void fork_init ();
838 pinfo_init (envp, envc);
840 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
841 old_title = title_buf;
843 /* Allocate cygheap->fdtab */
846 uinfo_init (); /* initialize user info */
848 wait_for_sigthread ();
849 extern DWORD threadfunc_ix;
851 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
853 /* Connect to tty. */
854 tty::init_session ();
856 /* Set internal locale to the environment settings. */
857 initial_setlocale ();
861 PWCHAR wline = GetCommandLineW ();
862 size_t size = sys_wcstombs (NULL, 0, wline);
863 char *line = (char *) alloca (size);
864 sys_wcstombs (line, size, wline);
866 /* Scan the command line and build argv. Expand wildcards if not
867 called from another cygwin process. */
868 build_argv (line, __argv, __argc,
869 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
871 /* Convert argv[0] to posix rules if it's currently blatantly
873 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
875 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
876 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
877 new_argv0, NT_MAX_PATH);
878 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
882 __argc_safe = __argc;
883 if (user_data->premain[0])
884 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
885 user_data->premain[i] (__argc, __argv, user_data);
887 /* Set up standard fds in file descriptor table. */
888 cygheap->fdtab.stdio_init ();
890 /* Set up __progname for getopt error call. */
891 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
894 __progname = __argv[0];
897 char *cp = strchr (__progname, '\0') - 4;
898 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
902 /* Set new console title if appropriate. */
904 if (display_title && !dynamically_loaded)
906 char *cp = __progname;
907 if (strip_title_path)
908 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
911 set_console_title (cp);
914 cygwin_finished_initializing = true;
915 /* Call init of loaded dlls. */
918 /* Execute any specified "premain" functions */
919 if (user_data->premain[PREMAIN_LEN / 2])
920 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
921 user_data->premain[i] (__argc, __argv, user_data);
923 debug_printf ("user_data->main %p", user_data->main);
925 if (dynamically_loaded)
931 /* Disable case-insensitive globbing */
932 ignore_case_with_glob = false;
937 cygbench (__progname);
939 /* Flush signals and ensure that signal thread is up and running. Can't
940 do this for noncygwin case since the signal thread is blocked due to
941 LoadLibrary serialization. */
944 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
946 .global __cygwin_exit_return \n\
947 __cygwin_exit_return: \n\
951 extern "C" void __stdcall
954 main_environ = user_data->envptr;
956 fork_info->alloc_stack ();
958 __sinit (_impure_ptr);
960 _main_tls = &_my_tls;
961 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
965 dll_crt0 (per_process *uptr)
967 /* Set the local copy of the pointer into the user space. */
968 if (!in_forkee && uptr && uptr != user_data)
970 memcpy (user_data, uptr, per_process_overwrite);
971 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
976 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
977 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
978 calling this function, and that storage must not be overwritten until you
979 unload cygwin1.dll, as it is used for _my_tls. It is best to load
980 cygwin1.dll before spawning any additional threads in your process.
982 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
983 from MSVC and non-cygwin MinGW applications. */
990 user_data->magic_biscuit = sizeof (per_process);
992 user_data->envptr = &envp;
993 user_data->fmode_ptr = &_fmode;
1001 /* Ordering is critical here. DLL ctors have already been
1002 run as they were being loaded, so we should stack the
1003 queued call to DLL dtors now. */
1004 atexit (dll_global_dtors);
1005 do_global_ctors (user_data->ctors, false);
1006 /* Now we have run global ctors, register their dtors. */
1007 atexit (do_global_dtors);
1008 /* At exit, global dtors will run first, so the app can still
1009 use shared library functions while terminating; then the
1010 DLLs will be destroyed; finally newlib will shut down stdio
1011 and terminate itself. */
1015 do_exit (int status)
1017 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1020 vfork_save *vf = vfork_storage.val ();
1021 if (vf != NULL && vf->pid < 0)
1023 exit_state = ES_NOT_EXITING;
1024 vf->restore_exit (status);
1028 lock_process until_exit (true);
1030 if (exit_state < ES_EVENTS_TERMINATE)
1032 exit_state = ES_EVENTS_TERMINATE;
1033 events_terminate ();
1036 UINT n = (UINT) status;
1037 if (exit_state < ES_THREADTERM)
1039 exit_state = ES_THREADTERM;
1040 cygthread::terminate ();
1043 if (exit_state < ES_SIGNAL)
1045 exit_state = ES_SIGNAL;
1046 signal (SIGCHLD, SIG_IGN);
1047 signal (SIGHUP, SIG_IGN);
1048 signal (SIGINT, SIG_IGN);
1049 signal (SIGQUIT, SIG_IGN);
1052 if (exit_state < ES_CLOSEALL)
1054 exit_state = ES_CLOSEALL;
1058 myself->stopsig = 0;
1060 if (exit_state < ES_HUP_PGRP)
1062 exit_state = ES_HUP_PGRP;
1063 /* Kill orphaned children on group leader exit */
1064 if (myself->has_pgid_children && myself->pid == myself->pgid)
1067 si.si_signo = -SIGHUP;
1068 si.si_code = SI_KERNEL;
1069 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1070 myself->pid, myself->pgid);
1071 kill_pgrp (myself->pgid, si);
1075 if (exit_state < ES_HUP_SID)
1077 exit_state = ES_HUP_SID;
1078 /* Kill the foreground process group on session leader exit */
1079 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1081 tty *tp = cygwin_shared->tty[myself->ctty];
1082 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1083 myself->pid, myself->sid);
1085 /* CGF FIXME: This can't be right. */
1086 if (tp->getsid () == myself->sid)
1087 tp->kill_pgrp (SIGHUP);
1092 if (exit_state < ES_TITLE)
1094 exit_state = ES_TITLE;
1095 /* restore console title */
1096 if (old_title && display_title)
1097 set_console_title (old_title);
1100 if (exit_state < ES_TTY_TERMINATE)
1102 exit_state = ES_TTY_TERMINATE;
1103 cygwin_shared->tty.terminate ();
1109 static NO_COPY muto atexit_lock;
1112 cygwin_atexit (void (*function)(void))
1115 atexit_lock.init ("atexit_lock");
1116 atexit_lock.acquire ();
1117 res = atexit (function);
1118 atexit_lock.release ();
1126 atexit_lock.acquire ();
1133 do_exit (((DWORD) n & 0xff) << 8);
1137 __api_fatal (const char *fmt, ...)
1143 int n = __small_sprintf (buf, "%P: *** fatal error - ");
1144 __small_vsprintf (buf + n, fmt, ap);
1146 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1151 myself.exit (__api_fatal_exit_val);
1155 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1157 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1159 child_proc_info->type = _PROC_WHOOPS;
1163 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
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 mismatch detected - %p/%p.\n\
1170 This problem is probably due to using incompatible versions of the cygwin DLL.\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. Rebooting is also suggested if you\n\
1175 are unable to find another cygwin DLL.",
1176 what, magic_version, version);
1181 cygbench (const char *s)
1183 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1184 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());