1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
4 2006, 2007 Red Hat, Inc.
6 This file is part of Cygwin.
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
17 #include "exceptions.h"
26 #include "perprocess.h"
32 #include "child_info_magic.h"
34 #include "shared_info.h"
35 #include "cygwin_version.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));
47 HANDLE NO_COPY hMainProc = (HANDLE) -1;
48 HANDLE NO_COPY hMainThread;
49 HANDLE NO_COPY hProcToken;
50 HANDLE NO_COPY hProcImpToken;
52 muto NO_COPY lock_process::locker;
55 bool strip_title_path;
56 bool allow_glob = true;
57 bool NO_COPY in_forkee;
60 int _declspec(dllexport) __argc;
61 char _declspec(dllexport) **__argv;
63 vfork_save NO_COPY *main_vfork;
66 static int NO_COPY envc;
69 extern "C" void __sinit (_reent *);
71 _cygtls NO_COPY *_main_tls;
73 bool NO_COPY cygwin_finished_initializing;
75 /* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
76 This is subtracted from the signal number prior to shifting the bit.
77 In older versions of cygwin, the signal was used as-is to shift the
78 bit for masking. So, we'll temporarily detect this and set it to zero
79 for programs that are linked using older cygwins. This is just a stopgap
80 measure to allow an orderly transfer to the new, correct sigmask method. */
81 unsigned NO_COPY int signal_shift_subtract = 1;
83 MTinterface _mtinterf;
85 bool NO_COPY _cygwin_testing;
87 char NO_COPY almost_null[1];
91 /* This is an exported copy of environ which can be used by DLLs
92 which use cygwin.dll. */
93 char **__cygwin_environ;
94 char ***main_environ = &__cygwin_environ;
95 /* __progname used in getopt error message */
97 struct per_process __cygwin_user_data =
98 {/* initial_sp */ 0, /* magic_biscuit */ 0,
99 /* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
100 /* dll_major */ CYGWIN_VERSION_DLL_MINOR,
101 /* impure_ptr_ptr */ NULL, /* envptr */ NULL,
102 /* malloc */ malloc, /* free */ free,
103 /* realloc */ realloc,
104 /* fmode_ptr */ NULL, /* main */ NULL, /* ctors */ NULL,
105 /* dtors */ NULL, /* data_start */ NULL, /* data_end */ NULL,
106 /* bss_start */ NULL, /* bss_end */ NULL,
108 /* premain */ {NULL, NULL, NULL, NULL},
110 /* unused */ {0, 0, 0, 0, 0, 0, 0},
111 /* UNUSED forkee */ 0,
113 /* api_major */ CYGWIN_VERSION_API_MAJOR,
114 /* api_minor */ CYGWIN_VERSION_API_MINOR,
115 /* unused2 */ {0, 0, 0, 0, 0, 0},
116 /* threadinterface */ &_mtinterf,
117 /* impure_ptr */ _GLOBAL_REENT,
119 bool ignore_case_with_glob;
120 int __declspec (dllexport) _check_for_executable = true;
124 int NO_COPY __api_fatal_exit_val = 1;
128 char title_buf[TITLESIZE + 1];
133 void (**pfunc) () = user_data->dtors;
136 user_data->dtors = NULL;
142 static void __stdcall
143 do_global_ctors (void (**in_pfunc)(), int force)
145 if (!force && in_forkee)
146 return; // inherit constructed stuff from parent pid
148 /* Run ctors backwards, so skip the first entry and find how many
149 there are, then run them. */
151 void (**pfunc) () = in_pfunc;
155 while (--pfunc > in_pfunc)
160 * Replaces @file in the command line with the contents of the file.
161 * There may be multiple @file's in a single command line
162 * A \@file is replaced with @file so that echo \@foo would print
163 * @foo and not the contents of foo.
165 static bool __stdcall
166 insert_file (char *name, char *&cmd)
171 f = CreateFile (name + 1,
172 GENERIC_READ, /* open for reading */
173 FILE_SHARE_READ, /* share for reading */
174 &sec_none_nih, /* no security */
175 OPEN_EXISTING, /* existing file only */
176 FILE_ATTRIBUTE_NORMAL, /* normal file */
177 NULL); /* no attr. template */
179 if (f == INVALID_HANDLE_VALUE)
181 debug_printf ("couldn't open file '%s', %E", name);
185 /* This only supports files up to about 4 billion bytes in
186 size. I am making the bold assumption that this is big
187 enough for this feature */
188 size = GetFileSize (f, NULL);
189 if (size == 0xFFFFFFFF)
191 debug_printf ("couldn't get file size for '%s', %E", name);
195 int new_size = strlen (cmd) + size + 2;
196 char *tmp = (char *) malloc (new_size);
199 debug_printf ("malloc failed, %E");
203 /* realloc passed as it should */
206 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
208 if (!rf_result || (rf_read != size))
210 debug_printf ("ReadFile failed, %E");
215 strcpy (tmp + size, cmd);
224 return ch == '"' || ch == '\'';
227 /* Step over a run of characters delimited by quotes */
228 static /*__inline*/ char *
229 quoted (char *cmd, int winshell)
237 strcpy (cmd, cmd + 1);
238 if (*(p = strechr (cmd, quote)))
243 const char *s = quote == '\'' ? "'" : "\\\"";
244 /* This must have been run from a Windows shell, so preserve
245 quotes for globify to play with later. */
246 while (*cmd && *++cmd)
247 if ((p = strpbrk (cmd, s)) == NULL)
249 cmd = strchr (cmd, '\0'); // no closing quote
254 else if (quote == '"' && p[1] == '"')
257 cmd = ++p; // a quoted quote
261 cmd = p + 1; // point to after end
267 /* Perform a glob on word if it contains wildcard characters.
268 Also quote every character between quotes to force glob to
269 treat the characters literally. */
271 globify (char *word, char **&argv, int &argc, int &argvlen)
273 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
278 int dos_spec = isdrive (word);
279 if (!dos_spec && isquote (*word) && word[1] && word[2])
280 dos_spec = isdrive (word + 1);
282 /* We'll need more space if there are quoting characters in
283 word. If that is the case, doubling the size of the
284 string should provide more than enough space. */
285 if (strpbrk (word, "'\""))
287 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
289 /* Fill pattern with characters from word, quoting any
290 characters found within quotes. */
291 for (p = pattern, s = word; *s != '\000'; s++, p++)
294 if (dos_spec && *s == '\\')
301 while (*++s && *s != quote)
303 if (dos_spec || *s != '\\')
305 else if (s[1] == quote || s[1] == '\\')
321 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
322 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
325 /* Allocate enough space in argv for the matched filenames. */
327 if ((argc += gl.gl_pathc) > argvlen)
330 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
333 /* Copy the matched filenames to argv. */
334 char **gv = gl.gl_pathv;
335 char **av = argv + n;
338 debug_printf ("argv[%d] = '%s'", n++, *gv);
342 /* Clean up after glob. */
347 /* Build argv, argc from string passed from Windows. */
349 static void __stdcall
350 build_argv (char *cmd, char **&argv, int &argc, int winshell)
353 int nesting = 0; // monitor "nesting" from insert_file
359 /* Scan command line until there is nothing left. */
369 /* Found the beginning of an argument. */
371 char *sawquote = NULL;
374 if (*cmd != '"' && (!winshell || *cmd != '\''))
375 cmd++; // Skip over this character
377 /* Skip over characters until the closing quote */
380 cmd = quoted (cmd, winshell && argc > 0);
382 if (issep (*cmd)) // End of argument if space
386 *cmd++ = '\0'; // Terminate `word'
388 /* Possibly look for @file construction assuming that this isn't
389 the very first argument and the @ wasn't quoted */
390 if (argc && sawquote != word && *word == '@')
392 if (++nesting > MAX_AT_FILE_LEVEL)
393 api_fatal ("Too many levels of nesting for %s", word);
394 if (insert_file (word, cmd))
395 continue; // There's new stuff in cmd now
398 /* See if we need to allocate more space for argv */
402 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
405 /* Add word to argv file after (optional) wildcard expansion. */
406 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
408 debug_printf ("argv[%d] = '%s'", argc, word);
415 debug_printf ("argc %d", argc);
418 /* sanity and sync check */
420 check_sanity_and_sync (per_process *p)
422 /* Sanity check to make sure developers didn't change the per_process */
423 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
424 /* about changing it]. */
425 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
426 api_fatal ("per_process sanity check failed");
428 /* Make sure that the app and the dll are in sync. */
430 /* Complain if older than last incompatible change */
431 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
432 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
433 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
435 /* magic_biscuit != 0 if using the old style version numbering scheme. */
436 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
437 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
438 p->magic_biscuit, SIZEOF_PER_PROCESS);
440 /* Complain if incompatible API changes made */
441 if (p->api_major > cygwin_version.api_major)
442 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
443 p->api_major, cygwin_version.api_major);
445 if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p->dll_major, p->dll_minor) <=
446 CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK)
447 signal_shift_subtract = 0;
450 child_info NO_COPY *child_proc_info = NULL;
452 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
455 child_info_fork::alloc_stack_hard_way (volatile char *b)
457 void *new_stack_pointer;
458 MEMORY_BASIC_INFORMATION m;
463 if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
464 api_fatal ("fork: couldn't get stack info, %E");
466 LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
468 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
471 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
476 newbase = (LPBYTE) stacktop - (128 * 1024);
477 newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
481 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
482 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
483 stacktop, stackbottom);
484 new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
485 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
486 PAGE_EXECUTE_READWRITE))
487 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
488 new_stack_pointer, stacksize);
489 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
490 api_fatal ("fork: couldn't get new stack info, %E");
494 m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
495 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
497 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
500 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
501 api_fatal ("fork: couldn't get new stack info, %E");
502 stacktop = m.BaseAddress;
506 void *getstack (void *) __attribute__ ((noinline));
508 getstack (volatile char * volatile p)
515 /* extend the stack prior to fork longjmp */
518 child_info_fork::alloc_stack ()
520 volatile char * volatile esp;
521 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
522 if (_tlsbase != stackbottom)
523 alloc_stack_hard_way (esp);
526 char *st = (char *) stacktop - 4096;
527 while (_tlstop >= st)
528 esp = getstack (esp);
536 static int NO_COPY sent_break;
539 debug_printf ("break here");
546 if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
552 if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
554 DWORD ms = atoi (buf);
556 len = GetModuleFileName (NULL, buf, PATH_MAX);
557 console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
559 if (!strace.active () && !dynamically_loaded)
562 if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
565 len = GetModuleFileName (NULL, buf1, PATH_MAX);
568 char *p = strpbrk (buf, ":=");
570 p = (char *) "gdb.exe -nw";
573 if (strstr (buf1, buf))
575 error_start_init (p);
577 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
586 get_cygwin_startup_info ()
590 GetStartupInfo (&si);
591 child_info *res = (child_info *) si.lpReserved2;
593 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
594 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
598 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
599 multiple_cygwin_problem ("proc intro", res->intro, 0);
600 else if (res->cygheap != (void *) &_cygheap_start)
601 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
602 (DWORD) &_cygheap_start);
604 unsigned should_be_cb = 0;
609 should_be_cb = sizeof (child_info_fork);
614 should_be_cb = sizeof (child_info_spawn);
615 if (should_be_cb != res->cb)
616 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
617 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
618 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
619 if (res->isstraced ())
622 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
623 low_priority_sleep (0);
628 system_printf ("unknown exec type %d", res->type);
629 /* intentionally fall through */
639 #define dll_data_start &_data_start__
640 #define dll_data_end &_data_end__
641 #define dll_bss_start &_bss_start__
642 #define dll_bss_end &_bss_end__
645 child_info_fork::handle_fork ()
647 cygheap_fixup_in_child (false);
650 myself->uid = cygheap->user.real_uid;
651 myself->gid = cygheap->user.real_gid;
653 child_copy (parent, false,
654 "dll data", dll_data_start, dll_data_end,
655 "dll bss", dll_bss_start, dll_bss_end,
656 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
658 /* step 2 now that the dll has its heap filled in, we can fill in the
659 user's data and bss since user_data is now filled out. */
660 child_copy (parent, false,
661 "data", user_data->data_start, user_data->data_end,
662 "bss", user_data->bss_start, user_data->bss_end,
665 if (fixup_mmaps_after_fork (parent))
666 api_fatal ("recreate_mmaps_after_fork_failed");
670 child_info_spawn::handle_spawn ()
673 cygheap_fixup_in_child (true);
675 if (!moreinfo->myself_pinfo ||
676 !DuplicateHandle (hMainProc, moreinfo->myself_pinfo, hMainProc, &h, 0,
677 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
680 __argc = moreinfo->argc;
681 __argv = moreinfo->argv;
682 envp = moreinfo->envp;
683 envc = moreinfo->envc;
684 if (!dynamically_loaded)
685 cygheap->fdtab.fixup_after_exec ();
687 cygheap->fdtab.move_fd (__stdin, 0);
689 cygheap->fdtab.move_fd (__stdout, 1);
693 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
694 handles might get confused. */
695 CloseHandle (child_proc_info->parent);
696 child_proc_info->parent = NULL;
698 signal_fixup_after_exec ();
699 if (moreinfo->old_title)
701 old_title = strcpy (title_buf, moreinfo->old_title);
702 cfree (moreinfo->old_title);
709 init_global_security ();
712 SetErrorMode (SEM_FAILCRITICALERRORS);
714 /* Initialize signal processing here, early, in the hopes that the creation
715 of a thread early in the process will cause more predictability in memory
716 layout for the main thread. */
719 lock_process::init ();
720 _impure_ptr = _GLOBAL_REENT;
721 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
722 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
723 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
724 _impure_ptr->_current_locale = "C";
725 user_data->impure_ptr = _impure_ptr;
726 user_data->impure_ptr_ptr = &_impure_ptr;
728 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
729 GetCurrentProcess (), &hMainProc, 0, FALSE,
730 DUPLICATE_SAME_ACCESS))
731 hMainProc = GetCurrentProcess ();
733 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
734 &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
736 OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
737 set_cygwin_privileges (hProcToken);
740 do_global_ctors (&__CTOR_LIST__, 1);
743 child_proc_info = get_cygwin_startup_info ();
744 if (!child_proc_info)
748 cygwin_user_h = child_proc_info->user_h;
749 switch (child_proc_info->type)
752 fork_info->handle_fork ();
756 spawn_info->handle_spawn ();
761 user_data->threadinterface->Init ();
765 /* Initialize events */
767 tty_list::init_session ();
769 cygheap->cwd.init ();
771 debug_printf ("finished dll_crt0_0 initialization");
774 /* Take over from libc's crt0.o and start the application. Note the
775 various special cases when Cygwin DLL is being runtime loaded (as
776 opposed to being link-time loaded by Cygwin apps) from a non
777 cygwin app via LoadLibrary. */
781 check_sanity_and_sync (user_data);
785 const int n = 2 * 1024 * 1024;
787 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
790 ProtectHandle (hMainProc);
791 ProtectHandle (hMainThread);
793 /* Initialize pthread mainthread when not forked and it is safe to call new,
794 otherwise it is reinitalized in fixup_after_fork */
796 pthread::init_mainthread ();
799 strace.microseconds ();
802 create_signal_arrived (); /* FIXME: move into wait_sig? */
804 /* Initialize debug muto, if DLL is built with --enable-debugging.
805 Need to do this before any helper threads start. */
809 cygheap->fdtab.vfork_child_fixup ();
810 main_vfork = vfork_storage.create ();
813 cygbench ("pre-forkee");
816 /* If we've played with the stack, stacksize != 0. That means that
817 fork() was invoked from other than the main thread. Make sure that
818 frame pointer is referencing the new stack so that the OS knows what
819 to do when it needs to increase the size of the stack.
821 NOTE: Don't do anything that involves the stack until you've completed
823 if (fork_info->stacksize)
825 _tlsbase = (char *) fork_info->stackbottom;
826 _tlstop = (char *) fork_info->stacktop;
827 _my_tls.init_exception_handler (_cygtls::handle_exceptions);
830 longjmp (fork_info->jmp, true);
835 extern void fork_init ();
839 pinfo_init (envp, envc);
841 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
842 old_title = title_buf;
844 /* Allocate cygheap->fdtab */
847 uinfo_init (); /* initialize user info */
849 wait_for_sigthread ();
850 extern DWORD threadfunc_ix;
852 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
854 /* Connect to tty. */
855 tty::init_session ();
859 char *line = GetCommandLineA ();
860 line = strcpy ((char *) alloca (strlen (line) + 1), line);
862 if (current_codepage == oem_cp)
863 CharToOemA (line, line);
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 (PATH_MAX);
875 cygwin_conv_to_posix_path (__argv[0], new_argv0);
876 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
880 __argc_safe = __argc;
881 if (user_data->premain[0])
882 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
883 user_data->premain[i] (__argc, __argv, user_data);
885 /* Set up standard fds in file descriptor table. */
886 cygheap->fdtab.stdio_init ();
888 /* Set up __progname for getopt error call. */
889 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
892 __progname = __argv[0];
895 char *cp = strchr (__progname, '\0') - 4;
896 if (cp > __progname && strcasematch (cp, ".exe"))
900 /* Set new console title if appropriate. */
902 if (display_title && !dynamically_loaded)
904 char *cp = __progname;
905 if (strip_title_path)
906 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
909 set_console_title (cp);
912 cygwin_finished_initializing = true;
913 /* Call init of loaded dlls. */
916 /* Execute any specified "premain" functions */
917 if (user_data->premain[PREMAIN_LEN / 2])
918 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
919 user_data->premain[i] (__argc, __argv, user_data);
921 debug_printf ("user_data->main %p", user_data->main);
923 if (dynamically_loaded)
929 /* Disable case-insensitive globbing */
930 ignore_case_with_glob = false;
935 cygbench (__progname);
937 /* Flush signals and ensure that signal thread is up and running. Can't
938 do this for noncygwin case since the signal thread is blocked due to
939 LoadLibrary serialization. */
942 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
945 extern "C" void __stdcall
948 main_environ = user_data->envptr;
950 fork_info->alloc_stack ();
952 __sinit (_impure_ptr);
954 _main_tls = &_my_tls;
955 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
959 dll_crt0 (per_process *uptr)
961 /* Set the local copy of the pointer into the user space. */
962 if (!in_forkee && uptr && uptr != user_data)
964 memcpy (user_data, uptr, per_process_overwrite);
965 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
970 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
971 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
972 calling this function, and that storage must not be overwritten until you
973 unload cygwin1.dll, as it is used for _my_tls. It is best to load
974 cygwin1.dll before spawning any additional threads in your process.
976 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
977 from MSVC and non-cygwin MinGW applications. */
984 user_data->magic_biscuit = sizeof (per_process);
986 user_data->envptr = &envp;
987 user_data->fmode_ptr = &_fmode;
995 do_global_ctors (user_data->ctors, false);
996 atexit (do_global_dtors);
999 exit_states NO_COPY exit_state;
1002 do_exit (int status)
1004 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1007 vfork_save *vf = vfork_storage.val ();
1008 if (vf != NULL && vf->pid < 0)
1010 exit_state = ES_NOT_EXITING;
1011 vf->restore_exit (status);
1015 lock_process until_exit (true);
1017 if (exit_state < ES_GLOBAL_DTORS)
1019 exit_state = ES_GLOBAL_DTORS;
1020 dll_global_dtors ();
1023 if (exit_state < ES_EVENTS_TERMINATE)
1025 exit_state = ES_EVENTS_TERMINATE;
1026 events_terminate ();
1029 UINT n = (UINT) status;
1030 if (exit_state < ES_THREADTERM)
1032 exit_state = ES_THREADTERM;
1033 cygthread::terminate ();
1036 if (exit_state < ES_SIGNAL)
1038 exit_state = ES_SIGNAL;
1039 signal (SIGCHLD, SIG_IGN);
1040 signal (SIGHUP, SIG_IGN);
1041 signal (SIGINT, SIG_IGN);
1042 signal (SIGQUIT, SIG_IGN);
1045 if (exit_state < ES_CLOSEALL)
1047 exit_state = ES_CLOSEALL;
1051 myself->stopsig = 0;
1053 if (exit_state < ES_HUP_PGRP)
1055 exit_state = ES_HUP_PGRP;
1056 /* Kill orphaned children on group leader exit */
1057 if (myself->has_pgid_children && myself->pid == myself->pgid)
1060 si.si_signo = -SIGHUP;
1061 si.si_code = SI_KERNEL;
1062 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1063 myself->pid, myself->pgid);
1064 kill_pgrp (myself->pgid, si);
1068 if (exit_state < ES_HUP_SID)
1070 exit_state = ES_HUP_SID;
1071 /* Kill the foreground process group on session leader exit */
1072 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1074 tty *tp = cygwin_shared->tty[myself->ctty];
1075 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1076 myself->pid, myself->sid);
1078 /* CGF FIXME: This can't be right. */
1079 if (tp->getsid () == myself->sid)
1080 tp->kill_pgrp (SIGHUP);
1085 if (exit_state < ES_TITLE)
1087 exit_state = ES_TITLE;
1088 /* restore console title */
1089 if (old_title && display_title)
1090 set_console_title (old_title);
1093 if (exit_state < ES_TTY_TERMINATE)
1095 exit_state = ES_TTY_TERMINATE;
1096 cygwin_shared->tty.terminate ();
1102 static NO_COPY muto atexit_lock;
1105 cygwin_atexit (void (*function)(void))
1108 atexit_lock.init ("atexit_lock");
1109 atexit_lock.acquire ();
1110 res = atexit (function);
1111 atexit_lock.release ();
1118 dll_global_dtors ();
1120 atexit_lock.acquire ();
1127 do_exit (((DWORD) n & 0xff) << 8);
1131 __api_fatal (const char *fmt, ...)
1137 int n = __small_sprintf (buf, "%P: *** fatal error - ");
1138 __small_vsprintf (buf + n, fmt, ap);
1140 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1145 myself.exit (__api_fatal_exit_val);
1149 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1151 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1153 child_proc_info->type = _PROC_WHOOPS;
1158 if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf, sizeof (buf)))
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)
1179 if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))
1180 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());