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 /* Initialize malloc and then call user_shared_initialize since it relies
770 on a functioning malloc and it's possible that the user's program may
771 have overridden malloc. We only know about that at this stage,
774 user_shared_initialize ();
778 const int n = 2 * 1024 * 1024;
780 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
783 ProtectHandle (hMainProc);
784 ProtectHandle (hMainThread);
786 cygheap->cwd.init ();
788 /* Initialize pthread mainthread when not forked and it is safe to call new,
789 otherwise it is reinitalized in fixup_after_fork */
791 pthread::init_mainthread ();
794 strace.microseconds ();
797 create_signal_arrived (); /* FIXME: move into wait_sig? */
799 /* Initialize debug muto, if DLL is built with --enable-debugging.
800 Need to do this before any helper threads start. */
804 cygheap->fdtab.vfork_child_fixup ();
805 main_vfork = vfork_storage.create ();
808 cygbench ("pre-forkee");
811 /* If we've played with the stack, stacksize != 0. That means that
812 fork() was invoked from other than the main thread. Make sure that
813 frame pointer is referencing the new stack so that the OS knows what
814 to do when it needs to increase the size of the stack.
816 NOTE: Don't do anything that involves the stack until you've completed
818 if (fork_info->stacksize)
820 _tlsbase = (char *) fork_info->stackbottom;
821 _tlstop = (char *) fork_info->stacktop;
822 _my_tls.init_exception_handler (_cygtls::handle_exceptions);
825 longjmp (fork_info->jmp, true);
830 extern void fork_init ();
834 pinfo_init (envp, envc);
836 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
837 old_title = title_buf;
839 /* Allocate cygheap->fdtab */
842 uinfo_init (); /* initialize user info */
844 wait_for_sigthread ();
845 extern DWORD threadfunc_ix;
847 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
849 /* Connect to tty. */
850 tty::init_session ();
854 PWCHAR wline = GetCommandLineW ();
855 size_t size = sys_wcstombs (NULL, 0, wline);
856 char *line = (char *) alloca (size);
857 sys_wcstombs (line, size, wline);
859 /* Scan the command line and build argv. Expand wildcards if not
860 called from another cygwin process. */
861 build_argv (line, __argv, __argc,
862 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
864 /* Convert argv[0] to posix rules if it's currently blatantly
866 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
868 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
869 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
870 new_argv0, NT_MAX_PATH);
871 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
875 __argc_safe = __argc;
876 if (user_data->premain[0])
877 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
878 user_data->premain[i] (__argc, __argv, user_data);
880 /* Set up standard fds in file descriptor table. */
881 cygheap->fdtab.stdio_init ();
883 /* Set up __progname for getopt error call. */
884 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
887 __progname = __argv[0];
890 char *cp = strchr (__progname, '\0') - 4;
891 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
895 /* Set new console title if appropriate. */
897 if (display_title && !dynamically_loaded)
899 char *cp = __progname;
900 if (strip_title_path)
901 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
904 set_console_title (cp);
907 cygwin_finished_initializing = true;
908 /* Call init of loaded dlls. */
911 /* Execute any specified "premain" functions */
912 if (user_data->premain[PREMAIN_LEN / 2])
913 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
914 user_data->premain[i] (__argc, __argv, user_data);
916 debug_printf ("user_data->main %p", user_data->main);
918 if (dynamically_loaded)
924 /* Disable case-insensitive globbing */
925 ignore_case_with_glob = false;
930 cygbench (__progname);
932 /* Flush signals and ensure that signal thread is up and running. Can't
933 do this for noncygwin case since the signal thread is blocked due to
934 LoadLibrary serialization. */
936 /* Reset current application locale to "C" per POSIX */
937 _setlocale_r (_REENT, LC_CTYPE, "C");
939 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
941 .global __cygwin_exit_return \n\
942 __cygwin_exit_return: \n\
946 extern "C" void __stdcall
949 main_environ = user_data->envptr;
951 fork_info->alloc_stack ();
953 __sinit (_impure_ptr);
955 _main_tls = &_my_tls;
956 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
960 dll_crt0 (per_process *uptr)
962 /* Set the local copy of the pointer into the user space. */
963 if (!in_forkee && uptr && uptr != user_data)
965 memcpy (user_data, uptr, per_process_overwrite);
966 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
971 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
972 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
973 calling this function, and that storage must not be overwritten until you
974 unload cygwin1.dll, as it is used for _my_tls. It is best to load
975 cygwin1.dll before spawning any additional threads in your process.
977 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
978 from MSVC and non-cygwin MinGW applications. */
985 user_data->magic_biscuit = sizeof (per_process);
987 user_data->envptr = &envp;
988 user_data->fmode_ptr = &_fmode;
996 /* Ordering is critical here. DLL ctors have already been
997 run as they were being loaded, so we should stack the
998 queued call to DLL dtors now. */
999 atexit (dll_global_dtors);
1000 do_global_ctors (user_data->ctors, false);
1001 /* Now we have run global ctors, register their dtors. */
1002 atexit (do_global_dtors);
1003 /* At exit, global dtors will run first, so the app can still
1004 use shared library functions while terminating; then the
1005 DLLs will be destroyed; finally newlib will shut down stdio
1006 and terminate itself. */
1010 do_exit (int status)
1012 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1015 vfork_save *vf = vfork_storage.val ();
1016 if (vf != NULL && vf->pid < 0)
1018 exit_state = ES_NOT_EXITING;
1019 vf->restore_exit (status);
1023 lock_process until_exit (true);
1025 if (exit_state < ES_EVENTS_TERMINATE)
1027 exit_state = ES_EVENTS_TERMINATE;
1028 events_terminate ();
1031 UINT n = (UINT) status;
1032 if (exit_state < ES_THREADTERM)
1034 exit_state = ES_THREADTERM;
1035 cygthread::terminate ();
1038 if (exit_state < ES_SIGNAL)
1040 exit_state = ES_SIGNAL;
1041 signal (SIGCHLD, SIG_IGN);
1042 signal (SIGHUP, SIG_IGN);
1043 signal (SIGINT, SIG_IGN);
1044 signal (SIGQUIT, SIG_IGN);
1047 if (exit_state < ES_CLOSEALL)
1049 exit_state = ES_CLOSEALL;
1053 myself->stopsig = 0;
1055 if (exit_state < ES_HUP_PGRP)
1057 exit_state = ES_HUP_PGRP;
1058 /* Kill orphaned children on group leader exit */
1059 if (myself->has_pgid_children && myself->pid == myself->pgid)
1062 si.si_signo = -SIGHUP;
1063 si.si_code = SI_KERNEL;
1064 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1065 myself->pid, myself->pgid);
1066 kill_pgrp (myself->pgid, si);
1070 if (exit_state < ES_HUP_SID)
1072 exit_state = ES_HUP_SID;
1073 /* Kill the foreground process group on session leader exit */
1074 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1076 tty *tp = cygwin_shared->tty[myself->ctty];
1077 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1078 myself->pid, myself->sid);
1080 /* CGF FIXME: This can't be right. */
1081 if (tp->getsid () == myself->sid)
1082 tp->kill_pgrp (SIGHUP);
1087 if (exit_state < ES_TITLE)
1089 exit_state = ES_TITLE;
1090 /* restore console title */
1091 if (old_title && display_title)
1092 set_console_title (old_title);
1095 if (exit_state < ES_TTY_TERMINATE)
1097 exit_state = ES_TTY_TERMINATE;
1098 cygwin_shared->tty.terminate ();
1104 static NO_COPY muto atexit_lock;
1107 cygwin_atexit (void (*function)(void))
1110 atexit_lock.init ("atexit_lock");
1111 atexit_lock.acquire ();
1112 res = atexit (function);
1113 atexit_lock.release ();
1121 atexit_lock.acquire ();
1128 do_exit (((DWORD) n & 0xff) << 8);
1132 __api_fatal (const char *fmt, ...)
1138 int n = __small_sprintf (buf, "%P: *** fatal error - ");
1139 __small_vsprintf (buf + n, fmt, ap);
1141 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1146 myself.exit (__api_fatal_exit_val);
1150 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1152 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1154 child_proc_info->type = _PROC_WHOOPS;
1158 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1161 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1162 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1164 api_fatal ("%s mismatch detected - %p/%p.\n\
1165 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1166 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1167 and delete all but the most recent version. The most recent version *should*\n\
1168 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1169 installed the cygwin distribution. Rebooting is also suggested if you\n\
1170 are unable to find another cygwin DLL.",
1171 what, magic_version, version);
1176 cygbench (const char *s)
1178 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1179 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());