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"
41 #define MAX_AT_FILE_LEVEL 10
43 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
45 extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
46 extern "C" void __sinit (_reent *);
48 static int NO_COPY envc;
49 static char NO_COPY **envp;
51 static char title_buf[TITLESIZE + 1];
53 bool NO_COPY jit_debug;
58 void (**pfunc) () = user_data->dtors;
61 user_data->dtors = NULL;
68 do_global_ctors (void (**in_pfunc)(), int force)
70 if (!force && in_forkee)
71 return; // inherit constructed stuff from parent pid
73 /* Run ctors backwards, so skip the first entry and find how many
74 there are, then run them. */
76 void (**pfunc) () = in_pfunc;
80 while (--pfunc > in_pfunc)
85 * Replaces @file in the command line with the contents of the file.
86 * There may be multiple @file's in a single command line
87 * A \@file is replaced with @file so that echo \@foo would print
88 * @foo and not the contents of foo.
91 insert_file (char *name, char *&cmd)
97 PWCHAR wname = tp.w_get ();
98 sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
99 f = CreateFileW (wname,
100 GENERIC_READ, /* open for reading */
101 FILE_SHARE_READ, /* share for reading */
102 &sec_none_nih, /* default security */
103 OPEN_EXISTING, /* existing file only */
104 FILE_ATTRIBUTE_NORMAL,/* normal file */
105 NULL); /* no attr. template */
107 if (f == INVALID_HANDLE_VALUE)
109 debug_printf ("couldn't open file '%s', %E", name);
113 /* This only supports files up to about 4 billion bytes in
114 size. I am making the bold assumption that this is big
115 enough for this feature */
116 size = GetFileSize (f, NULL);
117 if (size == 0xFFFFFFFF)
119 debug_printf ("couldn't get file size for '%s', %E", name);
123 int new_size = strlen (cmd) + size + 2;
124 char *tmp = (char *) malloc (new_size);
127 debug_printf ("malloc failed, %E");
131 /* realloc passed as it should */
134 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
136 if (!rf_result || (rf_read != size))
138 debug_printf ("ReadFile failed, %E");
143 strcpy (tmp + size, cmd);
152 return ch == '"' || ch == '\'';
155 /* Step over a run of characters delimited by quotes */
156 static /*__inline*/ char *
157 quoted (char *cmd, int winshell)
165 strcpy (cmd, cmd + 1);
166 if (*(p = strechr (cmd, quote)))
171 const char *s = quote == '\'' ? "'" : "\\\"";
172 /* This must have been run from a Windows shell, so preserve
173 quotes for globify to play with later. */
174 while (*cmd && *++cmd)
175 if ((p = strpbrk (cmd, s)) == NULL)
177 cmd = strchr (cmd, '\0'); // no closing quote
182 else if (quote == '"' && p[1] == '"')
185 cmd = ++p; // a quoted quote
189 cmd = p + 1; // point to after end
195 /* Perform a glob on word if it contains wildcard characters.
196 Also quote every character between quotes to force glob to
197 treat the characters literally. */
199 globify (char *word, char **&argv, int &argc, int &argvlen)
201 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
206 int dos_spec = isdrive (word);
207 if (!dos_spec && isquote (*word) && word[1] && word[2])
208 dos_spec = isdrive (word + 1);
210 /* We'll need more space if there are quoting characters in
211 word. If that is the case, doubling the size of the
212 string should provide more than enough space. */
213 if (strpbrk (word, "'\""))
215 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
217 /* Fill pattern with characters from word, quoting any
218 characters found within quotes. */
219 for (p = pattern, s = word; *s != '\000'; s++, p++)
222 if (dos_spec && *s == '\\')
229 while (*++s && *s != quote)
231 if (dos_spec || *s != '\\')
233 else if (s[1] == quote || s[1] == '\\')
236 size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
237 if (cnt <= 1 || cnt == (size_t)-1)
257 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
258 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
261 /* Allocate enough space in argv for the matched filenames. */
263 if ((argc += gl.gl_pathc) > argvlen)
266 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
269 /* Copy the matched filenames to argv. */
270 char **gv = gl.gl_pathv;
271 char **av = argv + n;
274 debug_printf ("argv[%d] = '%s'", n++, *gv);
278 /* Clean up after glob. */
283 /* Build argv, argc from string passed from Windows. */
285 static void __stdcall
286 build_argv (char *cmd, char **&argv, int &argc, int winshell)
289 int nesting = 0; // monitor "nesting" from insert_file
295 /* Scan command line until there is nothing left. */
305 /* Found the beginning of an argument. */
307 char *sawquote = NULL;
310 if (*cmd != '"' && (!winshell || *cmd != '\''))
311 cmd++; // Skip over this character
313 /* Skip over characters until the closing quote */
316 cmd = quoted (cmd, winshell && argc > 0);
318 if (issep (*cmd)) // End of argument if space
322 *cmd++ = '\0'; // Terminate `word'
324 /* Possibly look for @file construction assuming that this isn't
325 the very first argument and the @ wasn't quoted */
326 if (argc && sawquote != word && *word == '@')
328 if (++nesting > MAX_AT_FILE_LEVEL)
329 api_fatal ("Too many levels of nesting for %s", word);
330 if (insert_file (word, cmd))
331 continue; // There's new stuff in cmd now
334 /* See if we need to allocate more space for argv */
338 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
341 /* Add word to argv file after (optional) wildcard expansion. */
342 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
344 debug_printf ("argv[%d] = '%s'", argc, word);
351 debug_printf ("argc %d", argc);
354 /* sanity and sync check */
356 check_sanity_and_sync (per_process *p)
358 /* Sanity check to make sure developers didn't change the per_process */
359 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
360 /* about changing it]. */
361 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
362 api_fatal ("per_process sanity check failed");
364 /* Make sure that the app and the dll are in sync. */
366 /* Complain if older than last incompatible change */
367 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
368 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
369 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
371 /* magic_biscuit != 0 if using the old style version numbering scheme. */
372 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
373 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
374 p->magic_biscuit, SIZEOF_PER_PROCESS);
376 /* Complain if incompatible API changes made */
377 if (p->api_major > cygwin_version.api_major)
378 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
379 p->api_major, cygwin_version.api_major);
381 /* This is a kludge to work around a version of _cygwin_common_crt0
382 which overwrote the cxx_malloc field with the local DLL copy.
383 Hilarity ensues if the DLL is not loaded while the process
385 __cygwin_user_data.cxx_malloc = &default_cygwin_cxx_malloc;
388 child_info NO_COPY *child_proc_info = NULL;
390 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
393 child_info_fork::alloc_stack_hard_way (volatile char *b)
395 void *new_stack_pointer;
396 MEMORY_BASIC_INFORMATION m;
401 if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
402 api_fatal ("fork: couldn't get stack info, %E");
404 LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
406 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
409 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
414 newbase = (LPBYTE) stacktop - (128 * 1024);
415 newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
419 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
420 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
421 stacktop, stackbottom);
422 new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
423 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
424 PAGE_EXECUTE_READWRITE))
425 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
426 new_stack_pointer, stacksize);
427 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
428 api_fatal ("fork: couldn't get new stack info, %E");
432 m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
433 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
435 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
438 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
439 api_fatal ("fork: couldn't get new stack info, %E");
440 stacktop = m.BaseAddress;
444 void *getstack (void *) __attribute__ ((noinline));
446 getstack (volatile char * volatile p)
453 /* extend the stack prior to fork longjmp */
456 child_info_fork::alloc_stack ()
458 volatile char * volatile esp;
459 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
460 if (_tlsbase != stackbottom)
461 alloc_stack_hard_way (esp);
464 char *st = (char *) stacktop - 4096;
465 while (_tlstop >= st)
466 esp = getstack (esp);
474 static int NO_COPY sent_break;
477 debug_printf ("break here");
483 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
487 char buf[NT_MAX_PATH];
490 if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
492 DWORD ms = atoi (buf);
493 console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
495 if (!strace.active () && !dynamically_loaded)
498 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
500 char buf1[NT_MAX_PATH];
501 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
504 char *p = strpbrk (buf, ":=");
506 p = (char *) "gdb.exe -nw";
509 if (strstr (buf1, buf))
511 error_start_init (p);
514 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
523 get_cygwin_startup_info ()
527 GetStartupInfo (&si);
528 child_info *res = (child_info *) si.lpReserved2;
530 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
531 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
535 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
536 multiple_cygwin_problem ("proc intro", res->intro, 0);
537 else if (res->cygheap != (void *) &_cygheap_start)
538 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
539 (DWORD) &_cygheap_start);
541 unsigned should_be_cb = 0;
546 should_be_cb = sizeof (child_info_fork);
551 should_be_cb = sizeof (child_info_spawn);
552 if (should_be_cb != res->cb)
553 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
554 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
555 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
556 if (res->isstraced ())
559 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
565 system_printf ("unknown exec type %d", res->type);
566 /* intentionally fall through */
576 #define dll_data_start &_data_start__
577 #define dll_data_end &_data_end__
578 #define dll_bss_start &_bss_start__
579 #define dll_bss_end &_bss_end__
582 child_info_fork::handle_fork ()
584 cygheap_fixup_in_child (false);
586 myself.thisproc (NULL);
587 myself->uid = cygheap->user.real_uid;
588 myself->gid = cygheap->user.real_gid;
590 child_copy (parent, false,
591 "dll data", dll_data_start, dll_data_end,
592 "dll bss", dll_bss_start, dll_bss_end,
593 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
596 /* Do the relocations here. These will actually likely be overwritten by the
597 below child_copy but we do them here in case there is a read-only section
598 which does not get copied by fork. */
599 _pei386_runtime_relocator (user_data);
601 /* step 2 now that the dll has its heap filled in, we can fill in the
602 user's data and bss since user_data is now filled out. */
603 child_copy (parent, false,
604 "data", user_data->data_start, user_data->data_end,
605 "bss", user_data->bss_start, user_data->bss_end,
608 if (fixup_mmaps_after_fork (parent))
609 api_fatal ("recreate_mmaps_after_fork_failed");
613 child_info_spawn::handle_spawn ()
615 extern void fixup_lockf_after_exec ();
617 cygheap_fixup_in_child (true);
619 if (!moreinfo->myself_pinfo ||
620 !DuplicateHandle (GetCurrentProcess (), moreinfo->myself_pinfo,
621 GetCurrentProcess (), &h, 0,
622 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
625 __argc = moreinfo->argc;
626 __argv = moreinfo->argv;
627 envp = moreinfo->envp;
628 envc = moreinfo->envc;
629 if (!dynamically_loaded)
630 cygheap->fdtab.fixup_after_exec ();
632 cygheap->fdtab.move_fd (__stdin, 0);
634 cygheap->fdtab.move_fd (__stdout, 1);
635 cygheap->user.groups.clear_supp ();
639 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
640 handles might get confused. */
641 CloseHandle (child_proc_info->parent);
642 child_proc_info->parent = NULL;
644 signal_fixup_after_exec ();
645 if (moreinfo->old_title)
647 old_title = strcpy (title_buf, moreinfo->old_title);
648 cfree (moreinfo->old_title);
650 fixup_lockf_after_exec ();
654 /* Setting the TS-aware flag in the application's PE header is sufficient.
655 Just keep this in as a reminder. */
657 static DEP_SYSTEM_POLICY_TYPE dep_system_policy = (DEP_SYSTEM_POLICY_TYPE) -1;
665 if (dep_system_policy < 0)
667 dep_system_policy = GetSystemDEPPolicy ();
668 debug_printf ("DEP System Policy: %d", (int) dep_system_policy);
670 if (dep_system_policy < OptIn)
672 if (!GetProcessDEPPolicy (GetCurrentProcess (), &ppolicy, &perm))
674 debug_printf ("GetProcessDEPPolicy: %E");
677 debug_printf ("DEP Process Policy: %d (permanent = %d)", ppolicy, perm);
678 if (ppolicy > 0 && !perm && !SetProcessDEPPolicy (0))
679 debug_printf ("SetProcessDEPPolicy: %E");
683 /* Retrieve and store system directory for later use. Note that the
684 directory is stored with a trailing backslash! */
686 init_windows_system_directory ()
688 windows_system_directory_length =
689 GetSystemDirectoryW (windows_system_directory, MAX_PATH);
690 if (windows_system_directory_length == 0)
691 api_fatal ("can't find windows system directory");
692 windows_system_directory[windows_system_directory_length++] = L'\\';
693 windows_system_directory[windows_system_directory_length] = L'\0';
699 init_windows_system_directory ();
700 init_global_security ();
703 SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
705 lock_process::init ();
706 _impure_ptr = _GLOBAL_REENT;
707 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
708 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
709 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
710 _impure_ptr->_current_locale = "C";
711 user_data->impure_ptr = _impure_ptr;
712 user_data->impure_ptr_ptr = &_impure_ptr;
714 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
715 GetCurrentProcess (), &hMainThread,
716 0, false, DUPLICATE_SAME_ACCESS);
718 OpenProcessToken (GetCurrentProcess (), MAXIMUM_ALLOWED, &hProcToken);
719 set_cygwin_privileges (hProcToken);
722 do_global_ctors (&__CTOR_LIST__, 1);
725 child_proc_info = get_cygwin_startup_info ();
726 if (!child_proc_info)
730 cygwin_user_h = child_proc_info->user_h;
731 switch (child_proc_info->type)
734 fork_info->handle_fork ();
738 spawn_info->handle_spawn ();
743 user_data->threadinterface->Init ();
747 /* Initialize events */
749 tty_list::init_session ();
752 /* Setting the TS-aware flag in the application's PE header is sufficient.
753 Just keep this in as a reminder. */
755 /* The disable_dep function disables DEP for all Cygwin processes if
756 the process runs on a Windows Server 2008 with Terminal Services
757 installed. This combination (TS+DEP) breaks *some* Cygwin
758 applications. The Terminal Service specific DLL tsappcmp.dll
759 changes the page protection of some pages in the application's text
760 segment from PAGE_EXECUTE_WRITECOPY to PAGE_WRITECOPY for no
761 apparent reason. This occurs before any Cygwin or applicaton code
762 had a chance to run. MS has no explanation for this so far, but is
763 rather busy trying to avoid giving support for this problem (as of
766 Unfortunately disabling DEP seems to have a not negligible
767 performance hit. In the long run, either MS has to fix their
768 problem, or we have to find a better workaround, if any exists.
769 Idle idea: Adding EXECUTE protection to all text segment pages? */
770 if (wincap.ts_has_dep_problem ())
774 _main_tls = &_my_tls;
776 /* Initialize signal processing here, early, in the hopes that the creation
777 of a thread early in the process will cause more predictability in memory
778 layout for the main thread. */
779 if (!wincap.has_buggy_thread_startup () && !dynamically_loaded)
782 debug_printf ("finished dll_crt0_0 initialization");
785 /* Take over from libc's crt0.o and start the application. Note the
786 various special cases when Cygwin DLL is being runtime loaded (as
787 opposed to being link-time loaded by Cygwin apps) from a non
788 cygwin app via LoadLibrary. */
792 extern void initial_setlocale ();
794 if (wincap.has_buggy_thread_startup () || dynamically_loaded)
796 check_sanity_and_sync (user_data);
798 /* Initialize malloc and then call user_shared_initialize since it relies
799 on a functioning malloc and it's possible that the user's program may
800 have overridden malloc. We only know about that at this stage,
803 user_shared->initialize ();
807 const int n = 2 * 1024 * 1024;
809 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
812 ProtectHandle (hMainThread);
814 cygheap->cwd.init ();
816 /* Initialize pthread mainthread when not forked and it is safe to call new,
817 otherwise it is reinitalized in fixup_after_fork */
820 pthread::init_mainthread ();
821 _pei386_runtime_relocator (user_data);
825 strace.microseconds ();
828 create_signal_arrived (); /* FIXME: move into wait_sig? */
830 /* Initialize debug muto, if DLL is built with --enable-debugging.
831 Need to do this before any helper threads start. */
835 cygheap->fdtab.vfork_child_fixup ();
836 main_vfork = vfork_storage.create ();
839 cygbench ("pre-forkee");
842 /* If we've played with the stack, stacksize != 0. That means that
843 fork() was invoked from other than the main thread. Make sure that
844 frame pointer is referencing the new stack so that the OS knows what
845 to do when it needs to increase the size of the stack.
847 NOTE: Don't do anything that involves the stack until you've completed
849 if (fork_info->stacksize)
851 _tlsbase = (char *) fork_info->stackbottom;
852 _tlstop = (char *) fork_info->stacktop;
855 longjmp (fork_info->jmp, true);
858 __sinit (_impure_ptr);
862 extern void fork_init ();
866 pinfo_init (envp, envc);
868 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
869 old_title = title_buf;
871 /* Allocate cygheap->fdtab */
874 uinfo_init (); /* initialize user info */
876 /* Connect to tty. */
877 tty::init_session ();
879 /* Set internal locale to the environment settings. */
880 initial_setlocale ();
884 PWCHAR wline = GetCommandLineW ();
885 size_t size = sys_wcstombs (NULL, 0, wline);
886 char *line = (char *) alloca (size);
887 sys_wcstombs (line, size, wline);
889 /* Scan the command line and build argv. Expand wildcards if not
890 called from another cygwin process. */
891 build_argv (line, __argv, __argc,
892 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
894 /* Convert argv[0] to posix rules if it's currently blatantly
896 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
898 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
899 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
900 new_argv0, NT_MAX_PATH);
901 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
905 __argc_safe = __argc;
906 if (user_data->premain[0])
907 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
908 user_data->premain[i] (__argc, __argv, user_data);
910 /* Set up standard fds in file descriptor table. */
911 cygheap->fdtab.stdio_init ();
913 /* Set up __progname for getopt error call. */
914 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
917 __progname = __argv[0];
918 program_invocation_name = __argv[0];
919 program_invocation_short_name = __progname;
922 char *cp = strchr (__progname, '\0') - 4;
923 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
927 /* Set new console title if appropriate. */
929 if (display_title && !dynamically_loaded)
931 char *cp = __progname;
932 if (strip_title_path)
933 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
936 set_console_title (cp);
939 (void) xdr_set_vprintf (&cygxdr_vwarnx);
940 cygwin_finished_initializing = true;
941 /* Call init of loaded dlls. */
944 /* Execute any specified "premain" functions */
945 if (user_data->premain[PREMAIN_LEN / 2])
946 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
947 user_data->premain[i] (__argc, __argv, user_data);
951 if (dynamically_loaded)
954 /* Disable case-insensitive globbing */
955 ignore_case_with_glob = false;
958 cygbench (__progname);
961 /* Per POSIX set the default application locale back to "C". */
962 _setlocale_r (_REENT, LC_CTYPE, "C");
965 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
967 .global __cygwin_exit_return \n\
968 __cygwin_exit_return: \n\
972 extern "C" void __stdcall
975 main_environ = user_data->envptr;
978 fork_info->alloc_stack ();
979 _main_tls = &_my_tls;
982 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
986 dll_crt0 (per_process *uptr)
988 /* Set the local copy of the pointer into the user space. */
989 if (!in_forkee && uptr && uptr != user_data)
991 memcpy (user_data, uptr, per_process_overwrite);
992 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
997 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
998 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
999 calling this function, and that storage must not be overwritten until you
1000 unload cygwin1.dll, as it is used for _my_tls. It is best to load
1001 cygwin1.dll before spawning any additional threads in your process.
1003 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
1004 from MSVC and non-cygwin MinGW applications. */
1011 user_data->magic_biscuit = sizeof (per_process);
1013 user_data->envptr = &envp;
1014 user_data->fmode_ptr = &_fmode;
1022 /* Ordering is critical here. DLL ctors have already been
1023 run as they were being loaded, so we should stack the
1024 queued call to DLL dtors now. */
1025 atexit (dll_global_dtors);
1026 do_global_ctors (user_data->ctors, false);
1027 /* Now we have run global ctors, register their dtors.
1029 At exit, global dtors will run first, so the app can still
1030 use shared library functions while terminating; then the
1031 DLLs will be destroyed; finally newlib will shut down stdio
1032 and terminate itself. */
1033 atexit (do_global_dtors);
1034 sig_dispatch_pending (true);
1038 do_exit (int status)
1040 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1043 vfork_save *vf = vfork_storage.val ();
1044 if (vf != NULL && vf->pid < 0)
1046 exit_state = ES_NOT_EXITING;
1047 vf->restore_exit (status);
1051 lock_process until_exit (true);
1053 if (exit_state < ES_EVENTS_TERMINATE)
1055 exit_state = ES_EVENTS_TERMINATE;
1056 events_terminate ();
1059 if (exit_state < ES_SIGNAL)
1061 exit_state = ES_SIGNAL;
1062 signal (SIGCHLD, SIG_IGN);
1063 signal (SIGHUP, SIG_IGN);
1064 signal (SIGINT, SIG_IGN);
1065 signal (SIGQUIT, SIG_IGN);
1068 if (exit_state < ES_CLOSEALL)
1070 exit_state = ES_CLOSEALL;
1074 UINT n = (UINT) status;
1075 if (exit_state < ES_THREADTERM)
1077 exit_state = ES_THREADTERM;
1078 cygthread::terminate ();
1081 myself->stopsig = 0;
1083 if (exit_state < ES_HUP_PGRP)
1085 exit_state = ES_HUP_PGRP;
1086 /* Kill orphaned children on group leader exit */
1087 if (myself->has_pgid_children && myself->pid == myself->pgid)
1090 si.si_signo = -SIGHUP;
1091 si.si_code = SI_KERNEL;
1092 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1093 myself->pid, myself->pgid);
1094 kill_pgrp (myself->pgid, si);
1098 if (exit_state < ES_HUP_SID)
1100 exit_state = ES_HUP_SID;
1101 /* Kill the foreground process group on session leader exit */
1102 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1104 tty *tp = cygwin_shared->tty[myself->ctty];
1105 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1106 myself->pid, myself->sid);
1108 /* CGF FIXME: This can't be right. */
1109 if (tp->getsid () == myself->sid)
1110 tp->kill_pgrp (SIGHUP);
1115 if (exit_state < ES_TITLE)
1117 exit_state = ES_TITLE;
1118 /* restore console title */
1119 if (old_title && display_title)
1120 set_console_title (old_title);
1123 if (exit_state < ES_TTY_TERMINATE)
1125 exit_state = ES_TTY_TERMINATE;
1126 cygwin_shared->tty.terminate ();
1133 cygwin_atexit (void (*fn) (void))
1136 dll *d = dlls.find ((void *) _my_tls.retaddr ());
1137 res = d ? __cxa_atexit ((void (*) (void *)) fn, NULL, d) : atexit (fn);
1144 exit_state = ES_EXIT_STARTING;
1151 do_exit (((DWORD) n & 0xff) << 8);
1154 extern "C" void cygwin_stackdump ();
1157 __api_fatal (const char *fmt, ...)
1163 int n = __small_sprintf (buf, "%P: *** fatal error - ");
1164 __small_vsprintf (buf + n, fmt, ap);
1166 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1171 cygwin_stackdump ();
1172 myself.exit (__api_fatal_exit_val);
1176 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1178 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1180 child_proc_info->type = _PROC_WHOOPS;
1184 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1187 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1188 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1190 api_fatal ("%s mismatch detected - %p/%p.\n\
1191 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1192 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1193 and delete all but the most recent version. The most recent version *should*\n\
1194 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1195 installed the cygwin distribution. Rebooting is also suggested if you\n\
1196 are unable to find another cygwin DLL.",
1197 what, magic_version, version);
1202 cygbench (const char *s)
1204 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1205 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());