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);
380 child_info NO_COPY *child_proc_info = NULL;
382 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
385 child_info_fork::alloc_stack_hard_way (volatile char *b)
387 void *new_stack_pointer;
388 MEMORY_BASIC_INFORMATION m;
393 if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
394 api_fatal ("fork: couldn't get stack info, %E");
396 LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
398 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
401 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
406 newbase = (LPBYTE) stacktop - (128 * 1024);
407 newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
411 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
412 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
413 stacktop, stackbottom);
414 new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
415 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
416 PAGE_EXECUTE_READWRITE))
417 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
418 new_stack_pointer, stacksize);
419 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
420 api_fatal ("fork: couldn't get new stack info, %E");
424 m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
425 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
427 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
430 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
431 api_fatal ("fork: couldn't get new stack info, %E");
432 stacktop = m.BaseAddress;
436 void *getstack (void *) __attribute__ ((noinline));
438 getstack (volatile char * volatile p)
445 /* extend the stack prior to fork longjmp */
448 child_info_fork::alloc_stack ()
450 volatile char * volatile esp;
451 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
452 if (_tlsbase != stackbottom)
453 alloc_stack_hard_way (esp);
456 char *st = (char *) stacktop - 4096;
457 while (_tlstop >= st)
458 esp = getstack (esp);
466 static int NO_COPY sent_break;
469 debug_printf ("break here");
475 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
479 char buf[NT_MAX_PATH];
482 if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
484 DWORD ms = atoi (buf);
485 console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
487 if (!strace.active () && !dynamically_loaded)
490 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
492 char buf1[NT_MAX_PATH];
493 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
496 char *p = strpbrk (buf, ":=");
498 p = (char *) "gdb.exe -nw";
501 if (strstr (buf1, buf))
503 error_start_init (p);
506 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
515 get_cygwin_startup_info ()
519 GetStartupInfo (&si);
520 child_info *res = (child_info *) si.lpReserved2;
522 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
523 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
527 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
528 multiple_cygwin_problem ("proc intro", res->intro, 0);
529 else if (res->cygheap != (void *) &_cygheap_start)
530 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
531 (DWORD) &_cygheap_start);
533 unsigned should_be_cb = 0;
538 should_be_cb = sizeof (child_info_fork);
543 should_be_cb = sizeof (child_info_spawn);
544 if (should_be_cb != res->cb)
545 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
546 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
547 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
548 if (res->isstraced ())
551 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
552 low_priority_sleep (0);
557 system_printf ("unknown exec type %d", res->type);
558 /* intentionally fall through */
568 #define dll_data_start &_data_start__
569 #define dll_data_end &_data_end__
570 #define dll_bss_start &_bss_start__
571 #define dll_bss_end &_bss_end__
574 child_info_fork::handle_fork ()
576 cygheap_fixup_in_child (false);
578 myself.thisproc (NULL);
579 myself->uid = cygheap->user.real_uid;
580 myself->gid = cygheap->user.real_gid;
582 child_copy (parent, false,
583 "dll data", dll_data_start, dll_data_end,
584 "dll bss", dll_bss_start, dll_bss_end,
585 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
587 /* step 2 now that the dll has its heap filled in, we can fill in the
588 user's data and bss since user_data is now filled out. */
589 child_copy (parent, false,
590 "data", user_data->data_start, user_data->data_end,
591 "bss", user_data->bss_start, user_data->bss_end,
594 if (fixup_mmaps_after_fork (parent))
595 api_fatal ("recreate_mmaps_after_fork_failed");
599 child_info_spawn::handle_spawn ()
601 extern void fixup_lockf_after_exec ();
603 cygheap_fixup_in_child (true);
605 if (!moreinfo->myself_pinfo ||
606 !DuplicateHandle (hMainProc, moreinfo->myself_pinfo, hMainProc, &h, 0,
607 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
610 __argc = moreinfo->argc;
611 __argv = moreinfo->argv;
612 envp = moreinfo->envp;
613 envc = moreinfo->envc;
614 if (!dynamically_loaded)
615 cygheap->fdtab.fixup_after_exec ();
617 cygheap->fdtab.move_fd (__stdin, 0);
619 cygheap->fdtab.move_fd (__stdout, 1);
620 cygheap->user.groups.clear_supp ();
624 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
625 handles might get confused. */
626 CloseHandle (child_proc_info->parent);
627 child_proc_info->parent = NULL;
629 signal_fixup_after_exec ();
630 if (moreinfo->old_title)
632 old_title = strcpy (title_buf, moreinfo->old_title);
633 cfree (moreinfo->old_title);
635 fixup_lockf_after_exec ();
639 /* Setting the TS-aware flag in the application's PE header is sufficient.
640 Just keep this in as a reminder. */
642 static DEP_SYSTEM_POLICY_TYPE dep_system_policy = (DEP_SYSTEM_POLICY_TYPE) -1;
650 if (dep_system_policy < 0)
652 dep_system_policy = GetSystemDEPPolicy ();
653 debug_printf ("DEP System Policy: %d", (int) dep_system_policy);
655 if (dep_system_policy < OptIn)
657 if (!GetProcessDEPPolicy (hMainProc, &ppolicy, &perm))
659 debug_printf ("GetProcessDEPPolicy: %E");
662 debug_printf ("DEP Process Policy: %d (permanent = %d)", ppolicy, perm);
663 if (ppolicy > 0 && !perm && !SetProcessDEPPolicy (0))
664 debug_printf ("SetProcessDEPPolicy: %E");
671 init_global_security ();
674 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
676 /* Initialize signal processing here, early, in the hopes that the creation
677 of a thread early in the process will cause more predictability in memory
678 layout for the main thread. */
679 if (!dynamically_loaded)
682 lock_process::init ();
683 _impure_ptr = _GLOBAL_REENT;
684 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
685 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
686 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
687 _impure_ptr->_current_locale = "C";
688 user_data->impure_ptr = _impure_ptr;
689 user_data->impure_ptr_ptr = &_impure_ptr;
691 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
692 GetCurrentProcess (), &hMainProc, 0, FALSE,
693 DUPLICATE_SAME_ACCESS))
694 hMainProc = GetCurrentProcess ();
696 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
697 &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
699 OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
700 set_cygwin_privileges (hProcToken);
703 do_global_ctors (&__CTOR_LIST__, 1);
706 child_proc_info = get_cygwin_startup_info ();
707 if (!child_proc_info)
711 cygwin_user_h = child_proc_info->user_h;
712 switch (child_proc_info->type)
715 fork_info->handle_fork ();
719 spawn_info->handle_spawn ();
724 user_data->threadinterface->Init ();
728 /* Initialize events */
730 tty_list::init_session ();
733 /* Setting the TS-aware flag in the application's PE header is sufficient.
734 Just keep this in as a reminder. */
736 /* The disable_dep function disables DEP for all Cygwin processes if
737 the process runs on a Windows Server 2008 with Terminal Services
738 installed. This combination (TS+DEP) breaks *some* Cygwin
739 applications. The Terminal Service specific DLL tsappcmp.dll
740 changes the page protection of some pages in the application's text
741 segment from PAGE_EXECUTE_WRITECOPY to PAGE_WRITECOPY for no
742 apparent reason. This occurs before any Cygwin or applicaton code
743 had a chance to run. MS has no explanation for this so far, but is
744 rather busy trying to avoid giving support for this problem (as of
747 Unfortunately disabling DEP seems to have a not negligible
748 performance hit. In the long run, either MS has to fix their
749 problem, or we have to find a better workaround, if any exists.
750 Idle idea: Adding EXECUTE protection to all text segment pages? */
751 if (wincap.ts_has_dep_problem ())
755 debug_printf ("finished dll_crt0_0 initialization");
758 /* Take over from libc's crt0.o and start the application. Note the
759 various special cases when Cygwin DLL is being runtime loaded (as
760 opposed to being link-time loaded by Cygwin apps) from a non
761 cygwin app via LoadLibrary. */
765 if (dynamically_loaded)
767 check_sanity_and_sync (user_data);
769 /* This is a kludge to work around a version of _cygwin_common_crt0
770 which overwrote the cxx_malloc field with the local DLL copy.
771 Hilarity ensues if the DLL is not loaded like while the process
773 __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
775 /* Initialize malloc and then call user_shared_initialize since it relies
776 on a functioning malloc and it's possible that the user's program may
777 have overridden malloc. We only know about that at this stage,
780 user_shared_initialize ();
784 const int n = 2 * 1024 * 1024;
786 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
789 ProtectHandle (hMainProc);
790 ProtectHandle (hMainThread);
792 cygheap->cwd.init ();
794 /* Initialize pthread mainthread when not forked and it is safe to call new,
795 otherwise it is reinitalized in fixup_after_fork */
797 pthread::init_mainthread ();
800 strace.microseconds ();
803 create_signal_arrived (); /* FIXME: move into wait_sig? */
805 /* Initialize debug muto, if DLL is built with --enable-debugging.
806 Need to do this before any helper threads start. */
810 cygheap->fdtab.vfork_child_fixup ();
811 main_vfork = vfork_storage.create ();
814 cygbench ("pre-forkee");
817 /* If we've played with the stack, stacksize != 0. That means that
818 fork() was invoked from other than the main thread. Make sure that
819 frame pointer is referencing the new stack so that the OS knows what
820 to do when it needs to increase the size of the stack.
822 NOTE: Don't do anything that involves the stack until you've completed
824 if (fork_info->stacksize)
826 _tlsbase = (char *) fork_info->stackbottom;
827 _tlstop = (char *) fork_info->stacktop;
828 _my_tls.init_exception_handler (_cygtls::handle_exceptions);
831 longjmp (fork_info->jmp, true);
836 extern void fork_init ();
840 pinfo_init (envp, envc);
842 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
843 old_title = title_buf;
845 /* Allocate cygheap->fdtab */
848 uinfo_init (); /* initialize user info */
850 wait_for_sigthread ();
851 extern DWORD threadfunc_ix;
853 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
855 /* Connect to tty. */
856 tty::init_session ();
860 PWCHAR wline = GetCommandLineW ();
861 size_t size = sys_wcstombs (NULL, 0, wline);
862 char *line = (char *) alloca (size);
863 sys_wcstombs (line, size, wline);
865 /* Scan the command line and build argv. Expand wildcards if not
866 called from another cygwin process. */
867 build_argv (line, __argv, __argc,
868 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
870 /* Convert argv[0] to posix rules if it's currently blatantly
872 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
874 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
875 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
876 new_argv0, NT_MAX_PATH);
877 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
881 __argc_safe = __argc;
882 if (user_data->premain[0])
883 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
884 user_data->premain[i] (__argc, __argv, user_data);
886 /* Set up standard fds in file descriptor table. */
887 cygheap->fdtab.stdio_init ();
889 /* Set up __progname for getopt error call. */
890 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
893 __progname = __argv[0];
896 char *cp = strchr (__progname, '\0') - 4;
897 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
901 /* Set new console title if appropriate. */
903 if (display_title && !dynamically_loaded)
905 char *cp = __progname;
906 if (strip_title_path)
907 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
910 set_console_title (cp);
913 cygwin_finished_initializing = true;
914 /* Call init of loaded dlls. */
917 /* Execute any specified "premain" functions */
918 if (user_data->premain[PREMAIN_LEN / 2])
919 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
920 user_data->premain[i] (__argc, __argv, user_data);
922 debug_printf ("user_data->main %p", user_data->main);
924 if (dynamically_loaded)
930 /* Disable case-insensitive globbing */
931 ignore_case_with_glob = false;
936 cygbench (__progname);
938 /* Flush signals and ensure that signal thread is up and running. Can't
939 do this for noncygwin case since the signal thread is blocked due to
940 LoadLibrary serialization. */
942 /* Set internal locale to the environment settings. */
943 setlocale (LC_CTYPE, "");
944 /* Reset application locale to "C" per POSIX */
945 _setlocale_r (_REENT, LC_CTYPE, "C");
947 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
949 .global __cygwin_exit_return \n\
950 __cygwin_exit_return: \n\
954 extern "C" void __stdcall
957 main_environ = user_data->envptr;
959 fork_info->alloc_stack ();
961 __sinit (_impure_ptr);
963 _main_tls = &_my_tls;
964 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
968 dll_crt0 (per_process *uptr)
970 /* Set the local copy of the pointer into the user space. */
971 if (!in_forkee && uptr && uptr != user_data)
973 memcpy (user_data, uptr, per_process_overwrite);
974 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
979 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
980 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
981 calling this function, and that storage must not be overwritten until you
982 unload cygwin1.dll, as it is used for _my_tls. It is best to load
983 cygwin1.dll before spawning any additional threads in your process.
985 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
986 from MSVC and non-cygwin MinGW applications. */
993 user_data->magic_biscuit = sizeof (per_process);
995 user_data->envptr = &envp;
996 user_data->fmode_ptr = &_fmode;
1004 /* Ordering is critical here. DLL ctors have already been
1005 run as they were being loaded, so we should stack the
1006 queued call to DLL dtors now. */
1007 atexit (dll_global_dtors);
1008 do_global_ctors (user_data->ctors, false);
1009 /* Now we have run global ctors, register their dtors. */
1010 atexit (do_global_dtors);
1011 /* At exit, global dtors will run first, so the app can still
1012 use shared library functions while terminating; then the
1013 DLLs will be destroyed; finally newlib will shut down stdio
1014 and terminate itself. */
1018 do_exit (int status)
1020 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1023 vfork_save *vf = vfork_storage.val ();
1024 if (vf != NULL && vf->pid < 0)
1026 exit_state = ES_NOT_EXITING;
1027 vf->restore_exit (status);
1031 lock_process until_exit (true);
1033 if (exit_state < ES_EVENTS_TERMINATE)
1035 exit_state = ES_EVENTS_TERMINATE;
1036 events_terminate ();
1039 UINT n = (UINT) status;
1040 if (exit_state < ES_THREADTERM)
1042 exit_state = ES_THREADTERM;
1043 cygthread::terminate ();
1046 if (exit_state < ES_SIGNAL)
1048 exit_state = ES_SIGNAL;
1049 signal (SIGCHLD, SIG_IGN);
1050 signal (SIGHUP, SIG_IGN);
1051 signal (SIGINT, SIG_IGN);
1052 signal (SIGQUIT, SIG_IGN);
1055 if (exit_state < ES_CLOSEALL)
1057 exit_state = ES_CLOSEALL;
1061 myself->stopsig = 0;
1063 if (exit_state < ES_HUP_PGRP)
1065 exit_state = ES_HUP_PGRP;
1066 /* Kill orphaned children on group leader exit */
1067 if (myself->has_pgid_children && myself->pid == myself->pgid)
1070 si.si_signo = -SIGHUP;
1071 si.si_code = SI_KERNEL;
1072 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1073 myself->pid, myself->pgid);
1074 kill_pgrp (myself->pgid, si);
1078 if (exit_state < ES_HUP_SID)
1080 exit_state = ES_HUP_SID;
1081 /* Kill the foreground process group on session leader exit */
1082 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1084 tty *tp = cygwin_shared->tty[myself->ctty];
1085 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1086 myself->pid, myself->sid);
1088 /* CGF FIXME: This can't be right. */
1089 if (tp->getsid () == myself->sid)
1090 tp->kill_pgrp (SIGHUP);
1095 if (exit_state < ES_TITLE)
1097 exit_state = ES_TITLE;
1098 /* restore console title */
1099 if (old_title && display_title)
1100 set_console_title (old_title);
1103 if (exit_state < ES_TTY_TERMINATE)
1105 exit_state = ES_TTY_TERMINATE;
1106 cygwin_shared->tty.terminate ();
1112 static NO_COPY muto atexit_lock;
1115 cygwin_atexit (void (*function)(void))
1118 atexit_lock.init ("atexit_lock");
1119 atexit_lock.acquire ();
1120 res = atexit (function);
1121 atexit_lock.release ();
1129 atexit_lock.acquire ();
1136 do_exit (((DWORD) n & 0xff) << 8);
1140 __api_fatal (const char *fmt, ...)
1146 int n = __small_sprintf (buf, "%P: *** fatal error - ");
1147 __small_vsprintf (buf + n, fmt, ap);
1149 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1154 myself.exit (__api_fatal_exit_val);
1158 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1160 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1162 child_proc_info->type = _PROC_WHOOPS;
1166 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1169 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1170 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1172 api_fatal ("%s mismatch detected - %p/%p.\n\
1173 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1174 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1175 and delete all but the most recent version. The most recent version *should*\n\
1176 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1177 installed the cygwin distribution. Rebooting is also suggested if you\n\
1178 are unable to find another cygwin DLL.",
1179 what, magic_version, version);
1184 cygbench (const char *s)
1186 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1187 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());