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"
37 #include "exception.h"
40 #define MAX_AT_FILE_LEVEL 10
42 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
44 extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
45 extern "C" void __sinit (_reent *);
47 static int NO_COPY envc;
48 static char NO_COPY **envp;
50 static char title_buf[TITLESIZE + 1];
52 bool NO_COPY jit_debug;
57 void (**pfunc) () = user_data->dtors;
60 user_data->dtors = NULL;
67 do_global_ctors (void (**in_pfunc)(), int force)
69 if (!force && in_forkee)
70 return; // inherit constructed stuff from parent pid
72 /* Run ctors backwards, so skip the first entry and find how many
73 there are, then run them. */
75 void (**pfunc) () = in_pfunc;
79 while (--pfunc > in_pfunc)
84 * Replaces @file in the command line with the contents of the file.
85 * There may be multiple @file's in a single command line
86 * A \@file is replaced with @file so that echo \@foo would print
87 * @foo and not the contents of foo.
90 insert_file (char *name, char *&cmd)
96 PWCHAR wname = tp.w_get ();
97 sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
98 f = CreateFileW (wname,
99 GENERIC_READ, /* open for reading */
100 FILE_SHARE_READ, /* share for reading */
101 &sec_none_nih, /* default security */
102 OPEN_EXISTING, /* existing file only */
103 FILE_ATTRIBUTE_NORMAL,/* normal file */
104 NULL); /* no attr. template */
106 if (f == INVALID_HANDLE_VALUE)
108 debug_printf ("couldn't open file '%s', %E", name);
112 /* This only supports files up to about 4 billion bytes in
113 size. I am making the bold assumption that this is big
114 enough for this feature */
115 size = GetFileSize (f, NULL);
116 if (size == 0xFFFFFFFF)
118 debug_printf ("couldn't get file size for '%s', %E", name);
122 int new_size = strlen (cmd) + size + 2;
123 char *tmp = (char *) malloc (new_size);
126 debug_printf ("malloc failed, %E");
130 /* realloc passed as it should */
133 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
135 if (!rf_result || (rf_read != size))
137 debug_printf ("ReadFile failed, %E");
142 strcpy (tmp + size, cmd);
151 return ch == '"' || ch == '\'';
154 /* Step over a run of characters delimited by quotes */
155 static /*__inline*/ char *
156 quoted (char *cmd, int winshell)
164 strcpy (cmd, cmd + 1);
165 if (*(p = strechr (cmd, quote)))
170 const char *s = quote == '\'' ? "'" : "\\\"";
171 /* This must have been run from a Windows shell, so preserve
172 quotes for globify to play with later. */
173 while (*cmd && *++cmd)
174 if ((p = strpbrk (cmd, s)) == NULL)
176 cmd = strchr (cmd, '\0'); // no closing quote
181 else if (quote == '"' && p[1] == '"')
184 cmd = ++p; // a quoted quote
188 cmd = p + 1; // point to after end
194 /* Perform a glob on word if it contains wildcard characters.
195 Also quote every character between quotes to force glob to
196 treat the characters literally. */
198 globify (char *word, char **&argv, int &argc, int &argvlen)
200 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
205 int dos_spec = isdrive (word);
206 if (!dos_spec && isquote (*word) && word[1] && word[2])
207 dos_spec = isdrive (word + 1);
209 /* We'll need more space if there are quoting characters in
210 word. If that is the case, doubling the size of the
211 string should provide more than enough space. */
212 if (strpbrk (word, "'\""))
214 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
216 /* Fill pattern with characters from word, quoting any
217 characters found within quotes. */
218 for (p = pattern, s = word; *s != '\000'; s++, p++)
221 if (dos_spec && *s == '\\')
228 while (*++s && *s != quote)
230 if (dos_spec || *s != '\\')
232 else if (s[1] == quote || s[1] == '\\')
235 size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
236 if (cnt <= 1 || cnt == (size_t)-1)
256 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
257 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
260 /* Allocate enough space in argv for the matched filenames. */
262 if ((argc += gl.gl_pathc) > argvlen)
265 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
268 /* Copy the matched filenames to argv. */
269 char **gv = gl.gl_pathv;
270 char **av = argv + n;
273 debug_printf ("argv[%d] = '%s'", n++, *gv);
277 /* Clean up after glob. */
282 /* Build argv, argc from string passed from Windows. */
284 static void __stdcall
285 build_argv (char *cmd, char **&argv, int &argc, int winshell)
288 int nesting = 0; // monitor "nesting" from insert_file
294 /* Scan command line until there is nothing left. */
304 /* Found the beginning of an argument. */
306 char *sawquote = NULL;
309 if (*cmd != '"' && (!winshell || *cmd != '\''))
310 cmd++; // Skip over this character
312 /* Skip over characters until the closing quote */
315 cmd = quoted (cmd, winshell && argc > 0);
317 if (issep (*cmd)) // End of argument if space
321 *cmd++ = '\0'; // Terminate `word'
323 /* Possibly look for @file construction assuming that this isn't
324 the very first argument and the @ wasn't quoted */
325 if (argc && sawquote != word && *word == '@')
327 if (++nesting > MAX_AT_FILE_LEVEL)
328 api_fatal ("Too many levels of nesting for %s", word);
329 if (insert_file (word, cmd))
330 continue; // There's new stuff in cmd now
333 /* See if we need to allocate more space for argv */
337 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
340 /* Add word to argv file after (optional) wildcard expansion. */
341 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
343 debug_printf ("argv[%d] = '%s'", argc, word);
350 debug_printf ("argc %d", argc);
353 /* sanity and sync check */
355 check_sanity_and_sync (per_process *p)
357 /* Sanity check to make sure developers didn't change the per_process */
358 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
359 /* about changing it]. */
360 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
361 api_fatal ("per_process sanity check failed");
363 /* Make sure that the app and the dll are in sync. */
365 /* Complain if older than last incompatible change */
366 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
367 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
368 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
370 /* magic_biscuit != 0 if using the old style version numbering scheme. */
371 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
372 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
373 p->magic_biscuit, SIZEOF_PER_PROCESS);
375 /* Complain if incompatible API changes made */
376 if (p->api_major > cygwin_version.api_major)
377 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
378 p->api_major, cygwin_version.api_major);
380 /* This is a kludge to work around a version of _cygwin_common_crt0
381 which overwrote the cxx_malloc field with the local DLL copy.
382 Hilarity ensues if the DLL is not loaded while the process
384 __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
387 child_info NO_COPY *child_proc_info = NULL;
389 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
392 child_info_fork::alloc_stack_hard_way (volatile char *b)
394 void *new_stack_pointer;
395 MEMORY_BASIC_INFORMATION m;
400 if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
401 api_fatal ("fork: couldn't get stack info, %E");
403 LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
405 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
408 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
413 newbase = (LPBYTE) stacktop - (128 * 1024);
414 newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
418 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
419 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
420 stacktop, stackbottom);
421 new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
422 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
423 PAGE_EXECUTE_READWRITE))
424 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
425 new_stack_pointer, stacksize);
426 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
427 api_fatal ("fork: couldn't get new stack info, %E");
431 m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
432 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
434 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
437 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
438 api_fatal ("fork: couldn't get new stack info, %E");
439 stacktop = m.BaseAddress;
443 void *getstack (void *) __attribute__ ((noinline));
445 getstack (volatile char * volatile p)
452 /* extend the stack prior to fork longjmp */
455 child_info_fork::alloc_stack ()
457 volatile char * volatile esp;
458 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
459 if (_tlsbase != stackbottom)
460 alloc_stack_hard_way (esp);
463 char *st = (char *) stacktop - 4096;
464 while (_tlstop >= st)
465 esp = getstack (esp);
473 static int NO_COPY sent_break;
476 debug_printf ("break here");
482 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
486 char buf[NT_MAX_PATH];
489 if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
491 DWORD ms = atoi (buf);
492 console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
494 if (!strace.active () && !dynamically_loaded)
497 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
499 char buf1[NT_MAX_PATH];
500 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
503 char *p = strpbrk (buf, ":=");
505 p = (char *) "gdb.exe -nw";
508 if (strstr (buf1, buf))
510 error_start_init (p);
513 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
522 get_cygwin_startup_info ()
526 GetStartupInfo (&si);
527 child_info *res = (child_info *) si.lpReserved2;
529 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
530 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
534 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
535 multiple_cygwin_problem ("proc intro", res->intro, 0);
536 else if (res->cygheap != (void *) &_cygheap_start)
537 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
538 (DWORD) &_cygheap_start);
540 unsigned should_be_cb = 0;
545 should_be_cb = sizeof (child_info_fork);
550 should_be_cb = sizeof (child_info_spawn);
551 if (should_be_cb != res->cb)
552 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
553 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
554 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
555 if (res->isstraced ())
558 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
564 system_printf ("unknown exec type %d", res->type);
565 /* intentionally fall through */
575 #define dll_data_start &_data_start__
576 #define dll_data_end &_data_end__
577 #define dll_bss_start &_bss_start__
578 #define dll_bss_end &_bss_end__
581 child_info_fork::handle_fork ()
583 cygheap_fixup_in_child (false);
585 myself.thisproc (NULL);
586 myself->uid = cygheap->user.real_uid;
587 myself->gid = cygheap->user.real_gid;
589 child_copy (parent, false,
590 "dll data", dll_data_start, dll_data_end,
591 "dll bss", dll_bss_start, dll_bss_end,
592 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
595 /* Do the relocations here. These will actually likely be overwritten by the
596 below child_copy but we do them here in case there is a read-only section
597 which does not get copied by fork. */
598 _pei386_runtime_relocator (user_data);
600 /* step 2 now that the dll has its heap filled in, we can fill in the
601 user's data and bss since user_data is now filled out. */
602 child_copy (parent, false,
603 "data", user_data->data_start, user_data->data_end,
604 "bss", user_data->bss_start, user_data->bss_end,
607 if (fixup_mmaps_after_fork (parent))
608 api_fatal ("recreate_mmaps_after_fork_failed");
612 child_info_spawn::handle_spawn ()
614 extern void fixup_lockf_after_exec ();
616 cygheap_fixup_in_child (true);
618 if (!moreinfo->myself_pinfo ||
619 !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
620 GetCurrentProcess (), &h, 0,
621 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
624 __argc = moreinfo->argc;
625 __argv = moreinfo->argv;
626 envp = moreinfo->envp;
627 envc = moreinfo->envc;
628 if (!dynamically_loaded)
629 cygheap->fdtab.fixup_after_exec ();
631 cygheap->fdtab.move_fd (__stdin, 0);
633 cygheap->fdtab.move_fd (__stdout, 1);
634 cygheap->user.groups.clear_supp ();
638 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
639 handles might get confused. */
640 CloseHandle (child_proc_info->parent);
641 child_proc_info->parent = NULL;
643 signal_fixup_after_exec ();
644 if (moreinfo->old_title)
646 old_title = strcpy (title_buf, moreinfo->old_title);
647 cfree (moreinfo->old_title);
649 fixup_lockf_after_exec ();
653 /* Setting the TS-aware flag in the application's PE header is sufficient.
654 Just keep this in as a reminder. */
656 static DEP_SYSTEM_POLICY_TYPE dep_system_policy = (DEP_SYSTEM_POLICY_TYPE) -1;
664 if (dep_system_policy < 0)
666 dep_system_policy = GetSystemDEPPolicy ();
667 debug_printf ("DEP System Policy: %d", (int) dep_system_policy);
669 if (dep_system_policy < OptIn)
671 if (!GetProcessDEPPolicy (GetCurrentProcess (), &ppolicy, &perm))
673 debug_printf ("GetProcessDEPPolicy: %E");
676 debug_printf ("DEP Process Policy: %d (permanent = %d)", ppolicy, perm);
677 if (ppolicy > 0 && !perm && !SetProcessDEPPolicy (0))
678 debug_printf ("SetProcessDEPPolicy: %E");
685 init_global_security ();
688 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
690 /* Initialize signal processing here, early, in the hopes that the creation
691 of a thread early in the process will cause more predictability in memory
692 layout for the main thread. */
693 if (!dynamically_loaded)
696 lock_process::init ();
697 _impure_ptr = _GLOBAL_REENT;
698 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
699 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
700 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
701 _impure_ptr->_current_locale = "C";
702 user_data->impure_ptr = _impure_ptr;
703 user_data->impure_ptr_ptr = &_impure_ptr;
705 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
706 GetCurrentProcess (), &hMainThread,
707 0, false, DUPLICATE_SAME_ACCESS);
709 OpenProcessToken (GetCurrentProcess (), MAXIMUM_ALLOWED, &hProcToken);
710 set_cygwin_privileges (hProcToken);
713 do_global_ctors (&__CTOR_LIST__, 1);
716 child_proc_info = get_cygwin_startup_info ();
717 if (!child_proc_info)
721 cygwin_user_h = child_proc_info->user_h;
722 switch (child_proc_info->type)
725 fork_info->handle_fork ();
729 spawn_info->handle_spawn ();
734 user_data->threadinterface->Init ();
738 /* Initialize events */
740 tty_list::init_session ();
743 /* Setting the TS-aware flag in the application's PE header is sufficient.
744 Just keep this in as a reminder. */
746 /* The disable_dep function disables DEP for all Cygwin processes if
747 the process runs on a Windows Server 2008 with Terminal Services
748 installed. This combination (TS+DEP) breaks *some* Cygwin
749 applications. The Terminal Service specific DLL tsappcmp.dll
750 changes the page protection of some pages in the application's text
751 segment from PAGE_EXECUTE_WRITECOPY to PAGE_WRITECOPY for no
752 apparent reason. This occurs before any Cygwin or applicaton code
753 had a chance to run. MS has no explanation for this so far, but is
754 rather busy trying to avoid giving support for this problem (as of
757 Unfortunately disabling DEP seems to have a not negligible
758 performance hit. In the long run, either MS has to fix their
759 problem, or we have to find a better workaround, if any exists.
760 Idle idea: Adding EXECUTE protection to all text segment pages? */
761 if (wincap.ts_has_dep_problem ())
765 debug_printf ("finished dll_crt0_0 initialization");
768 /* Take over from libc's crt0.o and start the application. Note the
769 various special cases when Cygwin DLL is being runtime loaded (as
770 opposed to being link-time loaded by Cygwin apps) from a non
771 cygwin app via LoadLibrary. */
775 extern void initial_setlocale ();
777 if (dynamically_loaded)
779 check_sanity_and_sync (user_data);
781 /* Initialize malloc and then call user_shared_initialize since it relies
782 on a functioning malloc and it's possible that the user's program may
783 have overridden malloc. We only know about that at this stage,
786 user_shared->initialize ();
790 const int n = 2 * 1024 * 1024;
792 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
795 ProtectHandle (hMainThread);
797 cygheap->cwd.init ();
799 /* Initialize pthread mainthread when not forked and it is safe to call new,
800 otherwise it is reinitalized in fixup_after_fork */
803 pthread::init_mainthread ();
804 _pei386_runtime_relocator (user_data);
808 strace.microseconds ();
811 create_signal_arrived (); /* FIXME: move into wait_sig? */
813 /* Initialize debug muto, if DLL is built with --enable-debugging.
814 Need to do this before any helper threads start. */
818 cygheap->fdtab.vfork_child_fixup ();
819 main_vfork = vfork_storage.create ();
822 cygbench ("pre-forkee");
825 /* If we've played with the stack, stacksize != 0. That means that
826 fork() was invoked from other than the main thread. Make sure that
827 frame pointer is referencing the new stack so that the OS knows what
828 to do when it needs to increase the size of the stack.
830 NOTE: Don't do anything that involves the stack until you've completed
832 if (fork_info->stacksize)
834 _tlsbase = (char *) fork_info->stackbottom;
835 _tlstop = (char *) fork_info->stacktop;
838 longjmp (fork_info->jmp, true);
843 extern void fork_init ();
847 pinfo_init (envp, envc);
849 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
850 old_title = title_buf;
852 /* Allocate cygheap->fdtab */
855 uinfo_init (); /* initialize user info */
857 wait_for_sigthread ();
858 extern DWORD threadfunc_ix;
860 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
862 /* Connect to tty. */
863 tty::init_session ();
865 /* Set internal locale to the environment settings. */
866 initial_setlocale ();
870 PWCHAR wline = GetCommandLineW ();
871 size_t size = sys_wcstombs (NULL, 0, wline);
872 char *line = (char *) alloca (size);
873 sys_wcstombs (line, size, wline);
875 /* Scan the command line and build argv. Expand wildcards if not
876 called from another cygwin process. */
877 build_argv (line, __argv, __argc,
878 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
880 /* Convert argv[0] to posix rules if it's currently blatantly
882 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
884 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
885 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
886 new_argv0, NT_MAX_PATH);
887 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
891 __argc_safe = __argc;
892 if (user_data->premain[0])
893 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
894 user_data->premain[i] (__argc, __argv, user_data);
896 /* Set up standard fds in file descriptor table. */
897 cygheap->fdtab.stdio_init ();
899 /* Set up __progname for getopt error call. */
900 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
903 __progname = __argv[0];
906 char *cp = strchr (__progname, '\0') - 4;
907 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
911 /* Set new console title if appropriate. */
913 if (display_title && !dynamically_loaded)
915 char *cp = __progname;
916 if (strip_title_path)
917 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
920 set_console_title (cp);
923 (void) xdr_set_vprintf (&cygxdr_vwarnx);
924 cygwin_finished_initializing = true;
925 /* Call init of loaded dlls. */
928 /* Execute any specified "premain" functions */
929 if (user_data->premain[PREMAIN_LEN / 2])
930 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
931 user_data->premain[i] (__argc, __argv, user_data);
933 debug_printf ("user_data->main %p", user_data->main);
935 if (dynamically_loaded)
941 /* Disable case-insensitive globbing */
942 ignore_case_with_glob = false;
947 cygbench (__progname);
949 /* Flush signals and ensure that signal thread is up and running. Can't
950 do this for noncygwin case since the signal thread is blocked due to
951 LoadLibrary serialization. */
953 /* Per POSIX set the default application locale back to "C". */
954 _setlocale_r (_REENT, LC_CTYPE, "C");
956 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
958 .global __cygwin_exit_return \n\
959 __cygwin_exit_return: \n\
963 extern "C" void __stdcall
966 main_environ = user_data->envptr;
969 fork_info->alloc_stack ();
970 _main_tls = &_my_tls;
974 _main_tls = &_my_tls;
975 __sinit (_impure_ptr);
978 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
982 dll_crt0 (per_process *uptr)
984 /* Set the local copy of the pointer into the user space. */
985 if (!in_forkee && uptr && uptr != user_data)
987 memcpy (user_data, uptr, per_process_overwrite);
988 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
993 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
994 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
995 calling this function, and that storage must not be overwritten until you
996 unload cygwin1.dll, as it is used for _my_tls. It is best to load
997 cygwin1.dll before spawning any additional threads in your process.
999 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
1000 from MSVC and non-cygwin MinGW applications. */
1007 user_data->magic_biscuit = sizeof (per_process);
1009 user_data->envptr = &envp;
1010 user_data->fmode_ptr = &_fmode;
1018 /* Ordering is critical here. DLL ctors have already been
1019 run as they were being loaded, so we should stack the
1020 queued call to DLL dtors now. */
1021 atexit (dll_global_dtors);
1022 do_global_ctors (user_data->ctors, false);
1023 /* Now we have run global ctors, register their dtors. */
1024 atexit (do_global_dtors);
1025 /* At exit, global dtors will run first, so the app can still
1026 use shared library functions while terminating; then the
1027 DLLs will be destroyed; finally newlib will shut down stdio
1028 and terminate itself. */
1032 do_exit (int status)
1034 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1037 vfork_save *vf = vfork_storage.val ();
1038 if (vf != NULL && vf->pid < 0)
1040 exit_state = ES_NOT_EXITING;
1041 vf->restore_exit (status);
1045 lock_process until_exit (true);
1047 if (exit_state < ES_EVENTS_TERMINATE)
1049 exit_state = ES_EVENTS_TERMINATE;
1050 events_terminate ();
1053 UINT n = (UINT) status;
1054 if (exit_state < ES_THREADTERM)
1056 exit_state = ES_THREADTERM;
1057 cygthread::terminate ();
1060 if (exit_state < ES_SIGNAL)
1062 exit_state = ES_SIGNAL;
1063 signal (SIGCHLD, SIG_IGN);
1064 signal (SIGHUP, SIG_IGN);
1065 signal (SIGINT, SIG_IGN);
1066 signal (SIGQUIT, SIG_IGN);
1069 if (exit_state < ES_CLOSEALL)
1071 exit_state = ES_CLOSEALL;
1075 myself->stopsig = 0;
1077 if (exit_state < ES_HUP_PGRP)
1079 exit_state = ES_HUP_PGRP;
1080 /* Kill orphaned children on group leader exit */
1081 if (myself->has_pgid_children && myself->pid == myself->pgid)
1084 si.si_signo = -SIGHUP;
1085 si.si_code = SI_KERNEL;
1086 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1087 myself->pid, myself->pgid);
1088 kill_pgrp (myself->pgid, si);
1092 if (exit_state < ES_HUP_SID)
1094 exit_state = ES_HUP_SID;
1095 /* Kill the foreground process group on session leader exit */
1096 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1098 tty *tp = cygwin_shared->tty[myself->ctty];
1099 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1100 myself->pid, myself->sid);
1102 /* CGF FIXME: This can't be right. */
1103 if (tp->getsid () == myself->sid)
1104 tp->kill_pgrp (SIGHUP);
1109 if (exit_state < ES_TITLE)
1111 exit_state = ES_TITLE;
1112 /* restore console title */
1113 if (old_title && display_title)
1114 set_console_title (old_title);
1117 if (exit_state < ES_TTY_TERMINATE)
1119 exit_state = ES_TTY_TERMINATE;
1120 cygwin_shared->tty.terminate ();
1127 cygwin_atexit (void (*fn) (void))
1130 dll *d = dlls.find ((void *) _my_tls.retaddr ());
1131 res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
1138 exit_state = ES_EXIT_STARTING;
1145 do_exit (((DWORD) n & 0xff) << 8);
1149 __api_fatal (const char *fmt, ...)
1155 int n = __small_sprintf (buf, "%P: *** fatal error - ");
1156 __small_vsprintf (buf + n, fmt, ap);
1158 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1163 myself.exit (__api_fatal_exit_val);
1167 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1169 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1171 child_proc_info->type = _PROC_WHOOPS;
1175 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1178 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1179 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1181 api_fatal ("%s mismatch detected - %p/%p.\n\
1182 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1183 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1184 and delete all but the most recent version. The most recent version *should*\n\
1185 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1186 installed the cygwin distribution. Rebooting is also suggested if you\n\
1187 are unable to find another cygwin DLL.",
1188 what, magic_version, version);
1193 cygbench (const char *s)
1195 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1196 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());