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;
58 codepage_type current_codepage = ansi_cp;
61 int _declspec(dllexport) __argc;
62 char _declspec(dllexport) **__argv;
64 vfork_save NO_COPY *main_vfork;
67 static int NO_COPY envc;
70 extern "C" void __sinit (_reent *);
72 _cygtls NO_COPY *_main_tls;
74 bool NO_COPY cygwin_finished_initializing;
76 /* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
77 This is subtracted from the signal number prior to shifting the bit.
78 In older versions of cygwin, the signal was used as-is to shift the
79 bit for masking. So, we'll temporarily detect this and set it to zero
80 for programs that are linked using older cygwins. This is just a stopgap
81 measure to allow an orderly transfer to the new, correct sigmask method. */
82 unsigned NO_COPY int signal_shift_subtract = 1;
84 ResourceLocks _reslock NO_COPY;
85 MTinterface _mtinterf;
87 bool NO_COPY _cygwin_testing;
89 char NO_COPY almost_null[1];
93 /* This is an exported copy of environ which can be used by DLLs
94 which use cygwin.dll. */
95 char **__cygwin_environ;
96 char ***main_environ = &__cygwin_environ;
97 /* __progname used in getopt error message */
99 struct per_process __cygwin_user_data =
100 {/* initial_sp */ 0, /* magic_biscuit */ 0,
101 /* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
102 /* dll_major */ CYGWIN_VERSION_DLL_MINOR,
103 /* impure_ptr_ptr */ NULL, /* envptr */ NULL,
104 /* malloc */ malloc, /* free */ free,
105 /* realloc */ realloc,
106 /* fmode_ptr */ NULL, /* main */ NULL, /* ctors */ NULL,
107 /* dtors */ NULL, /* data_start */ NULL, /* data_end */ NULL,
108 /* bss_start */ NULL, /* bss_end */ NULL,
110 /* premain */ {NULL, NULL, NULL, NULL},
112 /* unused */ {0, 0, 0, 0, 0, 0, 0},
113 /* UNUSED forkee */ 0,
115 /* api_major */ CYGWIN_VERSION_API_MAJOR,
116 /* api_minor */ CYGWIN_VERSION_API_MINOR,
117 /* unused2 */ {0, 0, 0, 0, 0},
118 /* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf,
119 /* impure_ptr */ _GLOBAL_REENT,
121 bool ignore_case_with_glob;
122 int __declspec (dllexport) _check_for_executable = true;
126 int NO_COPY __api_fatal_exit_val = 1;
130 char title_buf[TITLESIZE + 1];
135 void (**pfunc) () = user_data->dtors;
138 user_data->dtors = NULL;
144 static void __stdcall
145 do_global_ctors (void (**in_pfunc)(), int force)
147 if (!force && in_forkee)
148 return; // inherit constructed stuff from parent pid
150 /* Run ctors backwards, so skip the first entry and find how many
151 there are, then run them. */
153 void (**pfunc) () = in_pfunc;
157 while (--pfunc > in_pfunc)
162 * Replaces @file in the command line with the contents of the file.
163 * There may be multiple @file's in a single command line
164 * A \@file is replaced with @file so that echo \@foo would print
165 * @foo and not the contents of foo.
167 static bool __stdcall
168 insert_file (char *name, char *&cmd)
173 f = CreateFile (name + 1,
174 GENERIC_READ, /* open for reading */
175 FILE_SHARE_READ, /* share for reading */
176 &sec_none_nih, /* no security */
177 OPEN_EXISTING, /* existing file only */
178 FILE_ATTRIBUTE_NORMAL, /* normal file */
179 NULL); /* no attr. template */
181 if (f == INVALID_HANDLE_VALUE)
183 debug_printf ("couldn't open file '%s', %E", name);
187 /* This only supports files up to about 4 billion bytes in
188 size. I am making the bold assumption that this is big
189 enough for this feature */
190 size = GetFileSize (f, NULL);
191 if (size == 0xFFFFFFFF)
193 debug_printf ("couldn't get file size for '%s', %E", name);
197 int new_size = strlen (cmd) + size + 2;
198 char *tmp = (char *) malloc (new_size);
201 debug_printf ("malloc failed, %E");
205 /* realloc passed as it should */
208 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
210 if (!rf_result || (rf_read != size))
212 debug_printf ("ReadFile failed, %E");
217 strcpy (tmp + size, cmd);
226 return ch == '"' || ch == '\'';
229 /* Step over a run of characters delimited by quotes */
230 static /*__inline*/ char *
231 quoted (char *cmd, int winshell)
239 strcpy (cmd, cmd + 1);
240 if (*(p = strechr (cmd, quote)))
245 const char *s = quote == '\'' ? "'" : "\\\"";
246 /* This must have been run from a Windows shell, so preserve
247 quotes for globify to play with later. */
248 while (*cmd && *++cmd)
249 if ((p = strpbrk (cmd, s)) == NULL)
251 cmd = strchr (cmd, '\0'); // no closing quote
256 else if (quote == '"' && p[1] == '"')
259 cmd = ++p; // a quoted quote
263 cmd = p + 1; // point to after end
269 /* Perform a glob on word if it contains wildcard characters.
270 Also quote every character between quotes to force glob to
271 treat the characters literally. */
273 globify (char *word, char **&argv, int &argc, int &argvlen)
275 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
280 int dos_spec = isdrive (word);
281 if (!dos_spec && isquote (*word) && word[1] && word[2])
282 dos_spec = isdrive (word + 1);
284 /* We'll need more space if there are quoting characters in
285 word. If that is the case, doubling the size of the
286 string should provide more than enough space. */
287 if (strpbrk (word, "'\""))
289 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
291 /* Fill pattern with characters from word, quoting any
292 characters found within quotes. */
293 for (p = pattern, s = word; *s != '\000'; s++, p++)
296 if (dos_spec && *s == '\\')
303 while (*++s && *s != quote)
305 if (dos_spec || *s != '\\')
307 else if (s[1] == quote || s[1] == '\\')
323 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
324 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
327 /* Allocate enough space in argv for the matched filenames. */
329 if ((argc += gl.gl_pathc) > argvlen)
332 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
335 /* Copy the matched filenames to argv. */
336 char **gv = gl.gl_pathv;
337 char **av = argv + n;
340 debug_printf ("argv[%d] = '%s'", n++, *gv);
344 /* Clean up after glob. */
349 /* Build argv, argc from string passed from Windows. */
351 static void __stdcall
352 build_argv (char *cmd, char **&argv, int &argc, int winshell)
355 int nesting = 0; // monitor "nesting" from insert_file
361 /* Scan command line until there is nothing left. */
371 /* Found the beginning of an argument. */
373 char *sawquote = NULL;
376 if (*cmd != '"' && (!winshell || *cmd != '\''))
377 cmd++; // Skip over this character
379 /* Skip over characters until the closing quote */
382 cmd = quoted (cmd, winshell && argc > 0);
384 if (issep (*cmd)) // End of argument if space
388 *cmd++ = '\0'; // Terminate `word'
390 /* Possibly look for @file construction assuming that this isn't
391 the very first argument and the @ wasn't quoted */
392 if (argc && sawquote != word && *word == '@')
394 if (++nesting > MAX_AT_FILE_LEVEL)
395 api_fatal ("Too many levels of nesting for %s", word);
396 if (insert_file (word, cmd))
397 continue; // There's new stuff in cmd now
400 /* See if we need to allocate more space for argv */
404 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
407 /* Add word to argv file after (optional) wildcard expansion. */
408 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
410 debug_printf ("argv[%d] = '%s'", argc, word);
417 debug_printf ("argc %d", argc);
420 /* sanity and sync check */
422 check_sanity_and_sync (per_process *p)
424 /* Sanity check to make sure developers didn't change the per_process */
425 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
426 /* about changing it]. */
427 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
428 api_fatal ("per_process sanity check failed");
430 /* Make sure that the app and the dll are in sync. */
432 /* Complain if older than last incompatible change */
433 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
434 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
435 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
437 /* magic_biscuit != 0 if using the old style version numbering scheme. */
438 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
439 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
440 p->magic_biscuit, SIZEOF_PER_PROCESS);
442 /* Complain if incompatible API changes made */
443 if (p->api_major > cygwin_version.api_major)
444 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
445 p->api_major, cygwin_version.api_major);
447 if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p->dll_major, p->dll_minor) <=
448 CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK)
449 signal_shift_subtract = 0;
452 child_info NO_COPY *child_proc_info = NULL;
454 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
457 child_info_fork::alloc_stack_hard_way (volatile char *b)
459 void *new_stack_pointer;
460 MEMORY_BASIC_INFORMATION m;
465 if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
466 api_fatal ("fork: couldn't get stack info, %E");
468 LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
470 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
473 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
478 newbase = (LPBYTE) stacktop - (128 * 1024);
479 newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
483 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
484 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
485 stacktop, stackbottom);
486 new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
487 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
488 PAGE_EXECUTE_READWRITE))
489 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
490 new_stack_pointer, stacksize);
491 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
492 api_fatal ("fork: couldn't get new stack info, %E");
496 m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
497 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
499 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
502 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
503 api_fatal ("fork: couldn't get new stack info, %E");
504 stacktop = m.BaseAddress;
508 void *getstack (void *) __attribute__ ((noinline));
510 getstack (volatile char * volatile p)
517 /* extend the stack prior to fork longjmp */
520 child_info_fork::alloc_stack ()
522 volatile char * volatile esp;
523 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
524 if (_tlsbase != stackbottom)
525 alloc_stack_hard_way (esp);
528 char *st = (char *) stacktop - 4096;
529 while (_tlstop >= st)
530 esp = getstack (esp);
538 static int NO_COPY sent_break;
541 debug_printf ("break here");
547 char buf[CYG_MAX_PATH];
548 if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
554 if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
556 DWORD ms = atoi (buf);
558 len = GetModuleFileName (NULL, buf, CYG_MAX_PATH);
559 console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
561 if (!strace.active () && !dynamically_loaded)
564 if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
566 char buf1[CYG_MAX_PATH];
567 len = GetModuleFileName (NULL, buf1, CYG_MAX_PATH);
570 char *p = strpbrk (buf, ":=");
572 p = (char *) "gdb.exe -nw";
575 if (strstr (buf1, buf))
577 error_start_init (p);
579 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
588 get_cygwin_startup_info ()
592 GetStartupInfo (&si);
593 child_info *res = (child_info *) si.lpReserved2;
595 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
596 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
600 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
601 multiple_cygwin_problem ("proc intro", res->intro, 0);
602 else if (res->cygheap != (void *) &_cygheap_start)
603 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
604 (DWORD) &_cygheap_start);
606 unsigned should_be_cb = 0;
611 should_be_cb = sizeof (child_info_fork);
616 should_be_cb = sizeof (child_info_spawn);
617 if (should_be_cb != res->cb)
618 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
619 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
620 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
621 if (res->isstraced ())
624 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
625 low_priority_sleep (0);
630 system_printf ("unknown exec type %d", res->type);
631 /* intentionally fall through */
641 #define dll_data_start &_data_start__
642 #define dll_data_end &_data_end__
643 #define dll_bss_start &_bss_start__
644 #define dll_bss_end &_bss_end__
647 child_info_fork::handle_fork ()
649 cygheap_fixup_in_child (false);
652 myself->uid = cygheap->user.real_uid;
653 myself->gid = cygheap->user.real_gid;
655 child_copy (parent, false,
656 "dll data", dll_data_start, dll_data_end,
657 "dll bss", dll_bss_start, dll_bss_end,
658 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
660 /* step 2 now that the dll has its heap filled in, we can fill in the
661 user's data and bss since user_data is now filled out. */
662 child_copy (parent, false,
663 "data", user_data->data_start, user_data->data_end,
664 "bss", user_data->bss_start, user_data->bss_end,
667 if (fixup_mmaps_after_fork (parent))
668 api_fatal ("recreate_mmaps_after_fork_failed");
672 child_info_spawn::handle_spawn ()
675 cygheap_fixup_in_child (true);
677 if (!moreinfo->myself_pinfo ||
678 !DuplicateHandle (hMainProc, moreinfo->myself_pinfo, hMainProc, &h, 0,
679 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
682 __argc = moreinfo->argc;
683 __argv = moreinfo->argv;
684 envp = moreinfo->envp;
685 envc = moreinfo->envc;
686 if (!dynamically_loaded)
687 cygheap->fdtab.fixup_after_exec ();
689 cygheap->fdtab.move_fd (__stdin, 0);
691 cygheap->fdtab.move_fd (__stdout, 1);
695 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
696 handles might get confused. */
697 CloseHandle (child_proc_info->parent);
698 child_proc_info->parent = NULL;
700 signal_fixup_after_exec ();
701 if (moreinfo->old_title)
703 old_title = strcpy (title_buf, moreinfo->old_title);
704 cfree (moreinfo->old_title);
711 init_global_security ();
714 SetErrorMode (SEM_FAILCRITICALERRORS);
716 /* Initialize signal processing here, early, in the hopes that the creation
717 of a thread early in the process will cause more predictability in memory
718 layout for the main thread. */
721 lock_process::init ();
722 _impure_ptr = _GLOBAL_REENT;
723 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
724 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
725 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
726 _impure_ptr->_current_locale = "C";
727 user_data->impure_ptr = _impure_ptr;
728 user_data->impure_ptr_ptr = &_impure_ptr;
730 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
731 GetCurrentProcess (), &hMainProc, 0, FALSE,
732 DUPLICATE_SAME_ACCESS))
733 hMainProc = GetCurrentProcess ();
735 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
736 &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
737 OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &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->resourcelocks->Init ();
762 user_data->threadinterface->Init ();
766 /* Initialize events */
768 tty_list::init_session ();
770 cygheap->cwd.init ();
772 debug_printf ("finished dll_crt0_0 initialization");
775 /* Take over from libc's crt0.o and start the application. Note the
776 various special cases when Cygwin DLL is being runtime loaded (as
777 opposed to being link-time loaded by Cygwin apps) from a non
778 cygwin app via LoadLibrary. */
782 check_sanity_and_sync (user_data);
786 const int n = 2 * 1024 * 1024;
788 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
791 ProtectHandle (hMainProc);
792 ProtectHandle (hMainThread);
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 /* Can be set only after environment has been initialized. */
843 set_cygwin_privileges (hProcToken);
845 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
846 old_title = title_buf;
848 /* Allocate cygheap->fdtab */
851 uinfo_init (); /* initialize user info */
853 wait_for_sigthread ();
854 extern DWORD threadfunc_ix;
856 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
858 /* Connect to tty. */
859 tty::init_session ();
863 char *line = GetCommandLineA ();
864 line = strcpy ((char *) alloca (strlen (line) + 1), line);
866 if (current_codepage == oem_cp)
867 CharToOemA (line, line);
869 /* Scan the command line and build argv. Expand wildcards if not
870 called from another cygwin process. */
871 build_argv (line, __argv, __argc,
872 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
874 /* Convert argv[0] to posix rules if it's currently blatantly
876 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
878 char *new_argv0 = (char *) malloc (CYG_MAX_PATH);
879 cygwin_conv_to_posix_path (__argv[0], new_argv0);
880 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
884 __argc_safe = __argc;
885 if (user_data->premain[0])
886 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
887 user_data->premain[i] (__argc, __argv, user_data);
889 /* Set up standard fds in file descriptor table. */
890 cygheap->fdtab.stdio_init ();
892 /* Set up __progname for getopt error call. */
893 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
896 __progname = __argv[0];
899 char *cp = strchr (__progname, '\0') - 4;
900 if (cp > __progname && strcasematch (cp, ".exe"))
904 /* Set new console title if appropriate. */
906 if (display_title && !dynamically_loaded)
908 char *cp = __progname;
909 if (strip_title_path)
910 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
913 set_console_title (cp);
916 cygwin_finished_initializing = true;
917 /* Call init of loaded dlls. */
920 /* Execute any specified "premain" functions */
921 if (user_data->premain[PREMAIN_LEN / 2])
922 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
923 user_data->premain[i] (__argc, __argv, user_data);
925 debug_printf ("user_data->main %p", user_data->main);
927 if (dynamically_loaded)
933 /* Disable case-insensitive globbing */
934 ignore_case_with_glob = false;
939 cygbench (__progname);
941 /* Flush signals and ensure that signal thread is up and running. Can't
942 do this for noncygwin case since the signal thread is blocked due to
943 LoadLibrary serialization. */
946 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
949 extern "C" void __stdcall
952 main_environ = user_data->envptr;
954 fork_info->alloc_stack ();
956 __sinit (_impure_ptr);
958 _main_tls = &_my_tls;
959 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
963 dll_crt0 (per_process *uptr)
965 /* Set the local copy of the pointer into the user space. */
966 if (!in_forkee && uptr && uptr != user_data)
968 memcpy (user_data, uptr, per_process_overwrite);
969 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
974 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
975 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
976 calling this function, and that storage must not be overwritten until you
977 unload cygwin1.dll, as it is used for _my_tls. It is best to load
978 cygwin1.dll before spawning any additional threads in your process.
980 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
981 from MSVC and non-cygwin MinGW applications. */
988 user_data->magic_biscuit = sizeof (per_process);
990 user_data->envptr = &envp;
991 user_data->fmode_ptr = &_fmode;
999 do_global_ctors (user_data->ctors, false);
1000 atexit (do_global_dtors);
1003 exit_states NO_COPY exit_state;
1006 do_exit (int status)
1008 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1011 vfork_save *vf = vfork_storage.val ();
1012 if (vf != NULL && vf->pid < 0)
1014 exit_state = ES_NOT_EXITING;
1015 vf->restore_exit (status);
1019 lock_process until_exit (true);
1021 if (exit_state < ES_GLOBAL_DTORS)
1023 exit_state = ES_GLOBAL_DTORS;
1024 dll_global_dtors ();
1027 if (exit_state < ES_EVENTS_TERMINATE)
1029 exit_state = ES_EVENTS_TERMINATE;
1030 events_terminate ();
1033 UINT n = (UINT) status;
1034 if (exit_state < ES_THREADTERM)
1036 exit_state = ES_THREADTERM;
1037 cygthread::terminate ();
1040 if (exit_state < ES_SIGNAL)
1042 exit_state = ES_SIGNAL;
1043 signal (SIGCHLD, SIG_IGN);
1044 signal (SIGHUP, SIG_IGN);
1045 signal (SIGINT, SIG_IGN);
1046 signal (SIGQUIT, SIG_IGN);
1049 if (exit_state < ES_CLOSEALL)
1051 exit_state = ES_CLOSEALL;
1055 myself->stopsig = 0;
1057 if (exit_state < ES_HUP_PGRP)
1059 exit_state = ES_HUP_PGRP;
1060 /* Kill orphaned children on group leader exit */
1061 if (myself->has_pgid_children && myself->pid == myself->pgid)
1064 si.si_signo = -SIGHUP;
1065 si.si_code = SI_KERNEL;
1066 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1067 myself->pid, myself->pgid);
1068 kill_pgrp (myself->pgid, si);
1072 if (exit_state < ES_HUP_SID)
1074 exit_state = ES_HUP_SID;
1075 /* Kill the foreground process group on session leader exit */
1076 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1078 tty *tp = cygwin_shared->tty[myself->ctty];
1079 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1080 myself->pid, myself->sid);
1082 /* CGF FIXME: This can't be right. */
1083 if (tp->getsid () == myself->sid)
1084 tp->kill_pgrp (SIGHUP);
1089 if (exit_state < ES_TITLE)
1091 exit_state = ES_TITLE;
1092 /* restore console title */
1093 if (old_title && display_title)
1094 set_console_title (old_title);
1097 if (exit_state < ES_TTY_TERMINATE)
1099 exit_state = ES_TTY_TERMINATE;
1100 cygwin_shared->tty.terminate ();
1106 static NO_COPY muto atexit_lock;
1109 cygwin_atexit (void (*function)(void))
1112 atexit_lock.init ("atexit_lock");
1113 atexit_lock.acquire ();
1114 res = atexit (function);
1115 atexit_lock.release ();
1122 dll_global_dtors ();
1124 atexit_lock.acquire ();
1131 do_exit (((DWORD) n & 0xff) << 8);
1135 __api_fatal (const char *fmt, ...)
1141 int n = __small_sprintf (buf, "%P: *** fatal error - ");
1142 __small_vsprintf (buf + n, fmt, ap);
1144 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1149 myself.exit (__api_fatal_exit_val);
1153 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1155 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1157 child_proc_info->type = _PROC_WHOOPS;
1162 if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf, sizeof (buf)))
1165 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1166 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1168 api_fatal ("%s mismatch detected - %p/%p.\n\
1169 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1170 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1171 and delete all but the most recent version. The most recent version *should*\n\
1172 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1173 installed the cygwin distribution. Rebooting is also suggested if you\n\
1174 are unable to find another cygwin DLL.",
1175 what, magic_version, version);
1180 cygbench (const char *s)
1183 if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))
1184 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());