1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
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"
40 #define MAX_AT_FILE_LEVEL 10
42 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
44 extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
46 HANDLE NO_COPY hMainProc = (HANDLE) -1;
47 HANDLE NO_COPY hMainThread;
48 HANDLE NO_COPY hProcToken;
49 HANDLE NO_COPY hProcImpToken;
51 muto NO_COPY lock_process::locker;
54 bool strip_title_path;
55 bool allow_glob = true;
56 bool NO_COPY in_forkee;
57 codepage_type current_codepage = ansi_cp;
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 ResourceLocks _reslock NO_COPY;
84 MTinterface _mtinterf;
86 bool NO_COPY _cygwin_testing;
88 char NO_COPY almost_null[1];
92 /* This is an exported copy of environ which can be used by DLLs
93 which use cygwin.dll. */
94 char **__cygwin_environ;
96 /* __progname used in getopt error message */
98 struct per_process __cygwin_user_data =
99 {/* initial_sp */ 0, /* magic_biscuit */ 0,
100 /* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
101 /* dll_major */ CYGWIN_VERSION_DLL_MINOR,
102 /* impure_ptr_ptr */ NULL, /* envptr */ NULL,
103 /* malloc */ malloc, /* free */ free,
104 /* realloc */ realloc,
105 /* fmode_ptr */ NULL, /* main */ NULL, /* ctors */ NULL,
106 /* dtors */ NULL, /* data_start */ NULL, /* data_end */ NULL,
107 /* bss_start */ NULL, /* bss_end */ NULL,
109 /* premain */ {NULL, NULL, NULL, NULL},
111 /* unused */ {0, 0, 0, 0, 0, 0, 0},
112 /* UNUSED forkee */ 0,
114 /* api_major */ CYGWIN_VERSION_API_MAJOR,
115 /* api_minor */ CYGWIN_VERSION_API_MINOR,
116 /* unused2 */ {0, 0, 0, 0, 0},
117 /* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf,
118 /* impure_ptr */ _GLOBAL_REENT,
120 bool ignore_case_with_glob;
121 int __declspec (dllexport) _check_for_executable = true;
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)
427 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;
453 static MEMORY_BASIC_INFORMATION NO_COPY sm;
455 #define CYGWIN_GUARD ((wincap.has_page_guard ()) ? \
456 PAGE_EXECUTE_READWRITE|PAGE_GUARD : PAGE_NOACCESS)
459 alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
461 void *new_stack_pointer;
462 MEMORY_BASIC_INFORMATION m;
465 LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;
468 if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)
471 newlen = (LPBYTE) ci->stackbottom - (LPBYTE) curbot;
476 newbase = ci->stacktop;
477 newlen = (DWORD) ci->stackbottom - (DWORD) ci->stacktop;
480 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
481 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
482 ci->stacktop, ci->stackbottom);
484 new_stack_pointer = (void *) ((LPBYTE) ci->stackbottom - ci->stacksize);
486 if (!VirtualAlloc (new_stack_pointer, ci->stacksize, MEM_COMMIT,
487 PAGE_EXECUTE_READWRITE))
488 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
489 new_stack_pointer, ci->stacksize);
490 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
491 api_fatal ("fork: couldn't get new stack info, %E");
494 m.BaseAddress = (LPVOID) ((DWORD) 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 ci->stacktop = m.BaseAddress;
506 void *getstack (void *) __attribute__ ((noinline));
508 getstack (volatile char * volatile p)
515 /* extend the stack prior to fork longjmp */
518 alloc_stack (child_info_fork *ci)
520 volatile char * volatile esp;
521 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
522 if (_tlsbase != ci->stackbottom)
523 alloc_stack_hard_way (ci, esp);
526 char *stacktop = (char *) ci->stacktop - 4096;
527 while (_tlstop >= stacktop)
528 esp = getstack (esp);
537 debug_printf ("break here");
544 char buf[CYG_MAX_PATH];
545 if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
551 if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
553 DWORD ms = atoi (buf);
555 len = GetModuleFileName (NULL, buf, CYG_MAX_PATH);
556 console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
558 if (!strace.active () && !dynamically_loaded)
561 if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
563 char buf1[CYG_MAX_PATH];
564 len = GetModuleFileName (NULL, buf1, CYG_MAX_PATH);
567 char *p = strpbrk (buf, ":=");
569 p = (char *) "gdb.exe -nw";
572 if (strstr (buf1, buf))
574 error_start_init (p);
576 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
586 get_cygwin_startup_info ()
589 char zeros[sizeof (child_proc_info->zero)] = {0};
591 GetStartupInfo (&si);
592 child_info *res = (child_info *) si.lpReserved2;
593 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
594 || memcmp (res->zero, zeros, sizeof (res->zero)) != 0)
598 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
599 multiple_cygwin_problem ("proc intro", res->intro, 0);
600 else if (res->intro == PROC_MAGIC_GENERIC
601 && res->magic != CHILD_INFO_MAGIC)
602 multiple_cygwin_problem ("proc magic", res->magic,
604 else if (res->cygheap != (void *) &_cygheap_start)
605 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
606 (DWORD) &_cygheap_start);
608 unsigned should_be_cb = 0;
613 should_be_cb = sizeof (child_info_fork);
618 should_be_cb = sizeof (child_info_spawn);
619 if (should_be_cb != res->cb)
620 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
621 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
622 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
626 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
627 low_priority_sleep (0);
632 system_printf ("unknown exec type %d", res->type);
633 /* intentionally fall through */
643 #define dll_data_start &_data_start__
644 #define dll_data_end &_data_end__
645 #define dll_bss_start &_bss_start__
646 #define dll_bss_end &_bss_end__
649 child_info_fork::handle_fork ()
651 cygheap_fixup_in_child (false);
654 child_copy (parent, false,
655 "dll data", dll_data_start, dll_data_end,
656 "dll bss", dll_bss_start, dll_bss_end,
657 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
659 /* step 2 now that the dll has its heap filled in, we can fill in the
660 user's data and bss since user_data is now filled out. */
661 child_copy (parent, false,
662 "data", user_data->data_start, user_data->data_end,
663 "bss", user_data->bss_start, user_data->bss_end,
666 if (fixup_mmaps_after_fork (parent))
667 api_fatal ("recreate_mmaps_after_fork_failed");
673 init_global_security ();
674 lock_process::init ();
675 init_console_handler (TRUE);
676 _impure_ptr = _GLOBAL_REENT;
677 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
678 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
679 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
680 _impure_ptr->_current_locale = "C";
681 user_data->impure_ptr = _impure_ptr;
682 user_data->impure_ptr_ptr = &_impure_ptr;
687 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
688 GetCurrentProcess (), &hMainProc, 0, FALSE,
689 DUPLICATE_SAME_ACCESS))
690 hMainProc = GetCurrentProcess ();
692 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
693 &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
694 if (wincap.has_security ())
695 OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
697 SetErrorMode (SEM_FAILCRITICALERRORS);
699 do_global_ctors (&__CTOR_LIST__, 1);
702 child_proc_info = get_cygwin_startup_info ();
703 if (!child_proc_info)
707 cygwin_user_h = child_proc_info->user_h;
708 switch (child_proc_info->type)
711 fork_info->handle_fork ();
716 cygheap_fixup_in_child (true);
718 if (!spawn_info->moreinfo->myself_pinfo ||
719 !DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
720 hMainProc, &h, 0, FALSE,
721 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
724 if (child_proc_info->type != _PROC_FORK)
725 child_proc_info->ready (true);
726 __argc = spawn_info->moreinfo->argc;
727 __argv = spawn_info->moreinfo->argv;
728 envp = spawn_info->moreinfo->envp;
729 envc = spawn_info->moreinfo->envc;
730 if (!dynamically_loaded)
731 cygheap->fdtab.fixup_after_exec ();
732 signal_fixup_after_exec ();
733 if (spawn_info->moreinfo->old_title)
735 old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
736 cfree (spawn_info->moreinfo->old_title);
744 /* Initialize events */
747 cygheap->cwd.init ();
749 /* Late duplicate simplifies tweaking the process token in uinfo.cc. */
750 if (wincap.has_security ())
751 DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL,
752 SecurityImpersonation, TokenImpersonation,
754 debug_printf ("finished dll_crt0_0 initialization");
757 /* Take over from libc's crt0.o and start the application. Note the
758 various special cases when Cygwin DLL is being runtime loaded (as
759 opposed to being link-time loaded by Cygwin apps) from a non
760 cygwin app via LoadLibrary. */
764 check_sanity_and_sync (user_data);
768 const int n = 2 * 1024 * 1024;
770 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
773 user_data->resourcelocks->Init ();
774 user_data->threadinterface->Init ();
775 ProtectHandle (hMainProc);
776 ProtectHandle (hMainThread);
778 /* Initialize pthread mainthread when not forked and it is safe to call new,
779 otherwise it is reinitalized in fixup_after_fork */
781 pthread::init_mainthread ();
784 strace.microseconds ();
787 create_signal_arrived ();
789 /* Initialize debug muto, if DLL is built with --enable-debugging.
790 Need to do this before any helper threads start. */
794 cygheap->fdtab.vfork_child_fixup ();
795 main_vfork = vfork_storage.create ();
798 cygbench ("pre-forkee");
801 /* If we've played with the stack, stacksize != 0. That means that
802 fork() was invoked from other than the main thread. Make sure that
803 frame pointer is referencing the new stack so that the OS knows what
804 to do when it needs to increase the size of the stack.
806 NOTE: Don't do anything that involves the stack until you've completed
808 if (fork_info->stacksize)
810 _tlsbase = (char *) fork_info->stackbottom;
811 _tlstop = (char *) fork_info->stacktop;
813 longjmp (fork_info->jmp, true);
818 extern void fork_init ();
823 /* Initialize our process table entry. */
824 pinfo_init (envp, envc);
826 /* Can be set only after environment has been initialized. */
827 if (wincap.has_security ())
828 set_cygwin_privileges (hProcImpToken);
830 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
831 old_title = title_buf;
833 /* Allocate cygheap->fdtab */
836 /* Initialize user info. */
839 /* Initialize signal/subprocess handling. */
842 /* Connect to tty. */
847 char *line = GetCommandLineA ();
848 line = strcpy ((char *) alloca (strlen (line) + 1), line);
850 if (current_codepage == oem_cp)
851 CharToOemA (line, line);
853 /* Scan the command line and build argv. Expand wildcards if not
854 called from another cygwin process. */
855 build_argv (line, __argv, __argc,
856 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
858 /* Convert argv[0] to posix rules if it's currently blatantly
860 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
862 char *new_argv0 = (char *) malloc (CYG_MAX_PATH);
863 cygwin_conv_to_posix_path (__argv[0], new_argv0);
864 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
868 __argc_safe = __argc;
869 if (user_data->premain[0])
870 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
871 user_data->premain[i] (__argc, __argv, user_data);
873 /* Set up standard fds in file descriptor table. */
874 cygheap->fdtab.stdio_init ();
876 /* Set up __progname for getopt error call. */
877 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
880 __progname = __argv[0];
883 char *cp = strchr (__progname, '\0') - 4;
884 if (cp > __progname && strcasematch (cp, ".exe"))
888 /* Set new console title if appropriate. */
890 if (display_title && !dynamically_loaded)
892 char *cp = __progname;
893 if (strip_title_path)
894 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
897 set_console_title (cp);
900 cygwin_finished_initializing = true;
901 /* Call init of loaded dlls. */
904 /* Execute any specified "premain" functions */
905 if (user_data->premain[PREMAIN_LEN / 2])
906 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
907 user_data->premain[i] (__argc, __argv, user_data);
909 debug_printf ("user_data->main %p", user_data->main);
911 if (dynamically_loaded)
917 /* Disable case-insensitive globbing */
918 ignore_case_with_glob = false;
923 cygbench (__progname);
925 /* Flush signals and ensure that signal thread is up and running. Can't
926 do this for noncygwin case since the signal thread is blocked due to
927 LoadLibrary serialization. */
928 wait_for_sigthread ();
931 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
935 initialize_main_tls (char *padding)
939 _main_tls = &_my_tls;
940 _main_tls->init_thread (padding, NULL);
942 return &_main_tls->local_clib;
945 /* Wrap the real one, otherwise gdb gets confused about
946 two symbols with the same name, but different addresses.
948 UPTR is a pointer to global data that lives on the libc side of the
949 line [if one distinguishes the application from the dll]. */
951 extern "C" void __stdcall
954 extern DWORD threadfunc_ix;
955 extern HANDLE sync_startup;
956 if (sync_startup != INVALID_HANDLE_VALUE)
958 WaitForSingleObject (sync_startup, INFINITE);
959 CloseHandle (sync_startup);
964 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
966 main_environ = user_data->envptr;
968 char padding[CYGTLS_PADSIZE];
971 alloc_stack (fork_info);
973 __sinit (_impure_ptr);
975 initialize_main_tls (padding);
976 dll_crt0_1 (padding);
980 dll_crt0 (per_process *uptr)
982 /* Set the local copy of the pointer into the user space. */
983 if (!in_forkee && uptr && uptr != user_data)
985 memcpy (user_data, uptr, per_process_overwrite);
986 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
991 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
992 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
993 calling this function, and that storage must not be overwritten until you
994 unload cygwin1.dll, as it is used for _my_tls. It is best to load
995 cygwin1.dll before spawning any additional threads in your process.
997 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
998 from MSVC and non-cygwin MinGW applications. */
1005 user_data->magic_biscuit = sizeof (per_process);
1007 user_data->envptr = &envp;
1008 user_data->fmode_ptr = &_fmode;
1016 do_global_ctors (user_data->ctors, false);
1017 atexit (do_global_dtors);
1020 exit_states NO_COPY exit_state;
1023 do_exit (int status)
1025 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1028 vfork_save *vf = vfork_storage.val ();
1029 if (vf != NULL && vf->pid < 0)
1031 exit_state = ES_NOT_EXITING;
1032 vf->restore_exit (status);
1036 lock_process until_exit (true);
1038 if (exit_state < ES_GLOBAL_DTORS)
1040 exit_state = ES_GLOBAL_DTORS;
1041 dll_global_dtors ();
1044 if (exit_state < ES_EVENTS_TERMINATE)
1046 exit_state = ES_EVENTS_TERMINATE;
1047 events_terminate ();
1050 UINT n = (UINT) status;
1051 if (exit_state < ES_THREADTERM)
1053 exit_state = ES_THREADTERM;
1054 cygthread::terminate ();
1057 if (exit_state < ES_SIGNAL)
1059 exit_state = ES_SIGNAL;
1060 signal (SIGCHLD, SIG_IGN);
1061 signal (SIGHUP, SIG_IGN);
1062 signal (SIGINT, SIG_IGN);
1063 signal (SIGQUIT, SIG_IGN);
1066 if (exit_state < ES_CLOSEALL)
1068 exit_state = ES_CLOSEALL;
1072 myself->stopsig = 0;
1074 if (exit_state < ES_HUP_PGRP)
1076 exit_state = ES_HUP_PGRP;
1077 /* Kill orphaned children on group leader exit */
1078 if (myself->has_pgid_children && myself->pid == myself->pgid)
1081 si.si_signo = -SIGHUP;
1082 si.si_code = SI_KERNEL;
1083 si.si_pid = si.si_uid = si.si_errno = 0;
1084 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1085 myself->pid, myself->pgid);
1086 kill_pgrp (myself->pgid, si);
1090 if (exit_state < ES_HUP_SID)
1092 exit_state = ES_HUP_SID;
1093 /* Kill the foreground process group on session leader exit */
1094 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1096 tty *tp = cygwin_shared->tty[myself->ctty];
1097 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1098 myself->pid, myself->sid);
1100 /* CGF FIXME: This can't be right. */
1101 if (tp->getsid () == myself->sid)
1102 tp->kill_pgrp (SIGHUP);
1107 if (exit_state < ES_TITLE)
1109 exit_state = ES_TITLE;
1110 /* restore console title */
1111 if (old_title && display_title)
1112 set_console_title (old_title);
1115 if (exit_state < ES_TTY_TERMINATE)
1117 exit_state = ES_TTY_TERMINATE;
1124 static NO_COPY muto atexit_lock;
1127 cygwin_atexit (void (*function)(void))
1130 atexit_lock.init ("atexit_lock");
1131 atexit_lock.acquire ();
1132 res = atexit (function);
1133 atexit_lock.release ();
1140 dll_global_dtors ();
1142 atexit_lock.acquire ();
1149 do_exit (((DWORD) n & 0xff) << 8);
1153 __api_fatal (const char *fmt, ...)
1159 int n = __small_sprintf (buf, "%P: *** fatal error - ", cygwin_pid (GetCurrentProcessId ()));
1160 __small_vsprintf (buf + n, fmt, ap);
1162 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1171 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1173 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1175 child_proc_info->type = _PROC_WHOOPS;
1180 if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf, sizeof (buf)))
1183 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1184 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1186 api_fatal ("%s mismatch detected - %p/%p.\n\
1187 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1188 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1189 and delete all but the most recent version. The most recent version *should*\n\
1190 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1191 installed the cygwin distribution. Rebooting is also suggested if you\n\
1192 are unable to find another cygwin DLL.",
1193 what, magic_version, version);
1198 cygbench (const char *s)
1201 if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))
1202 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());