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 codepage_type current_codepage = ansi_cp;
59 int _declspec(dllexport) __argc;
60 char _declspec(dllexport) **__argv;
62 vfork_save NO_COPY *main_vfork;
65 static int NO_COPY envc;
68 extern "C" void __sinit (_reent *);
70 _cygtls NO_COPY *_main_tls;
72 bool NO_COPY cygwin_finished_initializing;
74 /* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
75 This is subtracted from the signal number prior to shifting the bit.
76 In older versions of cygwin, the signal was used as-is to shift the
77 bit for masking. So, we'll temporarily detect this and set it to zero
78 for programs that are linked using older cygwins. This is just a stopgap
79 measure to allow an orderly transfer to the new, correct sigmask method. */
80 unsigned NO_COPY int signal_shift_subtract = 1;
82 ResourceLocks _reslock NO_COPY;
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;
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},
113 /* api_major */ CYGWIN_VERSION_API_MAJOR,
114 /* api_minor */ CYGWIN_VERSION_API_MINOR,
115 /* unused2 */ {0, 0, 0, 0, 0},
116 /* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf,
117 /* impure_ptr */ _GLOBAL_REENT,
119 bool ignore_case_with_glob;
120 int __declspec (dllexport) _check_for_executable = true;
127 char title_buf[TITLESIZE + 1];
132 void (**pfunc) () = user_data->dtors;
135 user_data->dtors = NULL;
141 static void __stdcall
142 do_global_ctors (void (**in_pfunc)(), int force)
144 if (!force && user_data->forkee)
145 return; // inherit constructed stuff from parent pid
147 /* Run ctors backwards, so skip the first entry and find how many
148 there are, then run them. */
150 void (**pfunc) () = in_pfunc;
154 while (--pfunc > in_pfunc)
159 * Replaces @file in the command line with the contents of the file.
160 * There may be multiple @file's in a single command line
161 * A \@file is replaced with @file so that echo \@foo would print
162 * @foo and not the contents of foo.
164 static bool __stdcall
165 insert_file (char *name, char *&cmd)
170 f = CreateFile (name + 1,
171 GENERIC_READ, /* open for reading */
172 FILE_SHARE_READ, /* share for reading */
173 &sec_none_nih, /* no security */
174 OPEN_EXISTING, /* existing file only */
175 FILE_ATTRIBUTE_NORMAL, /* normal file */
176 NULL); /* no attr. template */
178 if (f == INVALID_HANDLE_VALUE)
180 debug_printf ("couldn't open file '%s', %E", name);
184 /* This only supports files up to about 4 billion bytes in
185 size. I am making the bold assumption that this is big
186 enough for this feature */
187 size = GetFileSize (f, NULL);
188 if (size == 0xFFFFFFFF)
190 debug_printf ("couldn't get file size for '%s', %E", name);
194 int new_size = strlen (cmd) + size + 2;
195 char *tmp = (char *) malloc (new_size);
198 debug_printf ("malloc failed, %E");
202 /* realloc passed as it should */
205 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
207 if (!rf_result || (rf_read != size))
209 debug_printf ("ReadFile failed, %E");
214 strcpy (tmp + size, cmd);
223 return ch == '"' || ch == '\'';
226 /* Step over a run of characters delimited by quotes */
227 static /*__inline*/ char *
228 quoted (char *cmd, int winshell)
236 strcpy (cmd, cmd + 1);
237 if (*(p = strechr (cmd, quote)))
242 const char *s = quote == '\'' ? "'" : "\\\"";
243 /* This must have been run from a Windows shell, so preserve
244 quotes for globify to play with later. */
245 while (*cmd && *++cmd)
246 if ((p = strpbrk (cmd, s)) == NULL)
248 cmd = strchr (cmd, '\0'); // no closing quote
253 else if (quote == '"' && p[1] == '"')
256 cmd = ++p; // a quoted quote
260 cmd = p + 1; // point to after end
266 /* Perform a glob on word if it contains wildcard characters.
267 Also quote every character between quotes to force glob to
268 treat the characters literally. */
270 globify (char *word, char **&argv, int &argc, int &argvlen)
272 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
277 int dos_spec = isdrive (word);
278 if (!dos_spec && isquote (*word) && word[1] && word[2])
279 dos_spec = isdrive (word + 1);
281 /* We'll need more space if there are quoting characters in
282 word. If that is the case, doubling the size of the
283 string should provide more than enough space. */
284 if (strpbrk (word, "'\""))
286 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
288 /* Fill pattern with characters from word, quoting any
289 characters found within quotes. */
290 for (p = pattern, s = word; *s != '\000'; s++, p++)
293 if (dos_spec && *s == '\\')
300 while (*++s && *s != quote)
302 if (dos_spec || *s != '\\')
304 else if (s[1] == quote || s[1] == '\\')
320 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
321 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
324 /* Allocate enough space in argv for the matched filenames. */
326 if ((argc += gl.gl_pathc) > argvlen)
329 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
332 /* Copy the matched filenames to argv. */
333 char **gv = gl.gl_pathv;
334 char **av = argv + n;
337 debug_printf ("argv[%d] = '%s'", n++, *gv);
341 /* Clean up after glob. */
346 /* Build argv, argc from string passed from Windows. */
348 static void __stdcall
349 build_argv (char *cmd, char **&argv, int &argc, int winshell)
352 int nesting = 0; // monitor "nesting" from insert_file
358 /* Scan command line until there is nothing left. */
368 /* Found the beginning of an argument. */
370 char *sawquote = NULL;
373 if (*cmd != '"' && (!winshell || *cmd != '\''))
374 cmd++; // Skip over this character
376 /* Skip over characters until the closing quote */
379 cmd = quoted (cmd, winshell && argc > 0);
381 if (issep (*cmd)) // End of argument if space
385 *cmd++ = '\0'; // Terminate `word'
387 /* Possibly look for @file construction assuming that this isn't
388 the very first argument and the @ wasn't quoted */
389 if (argc && sawquote != word && *word == '@')
391 if (++nesting > MAX_AT_FILE_LEVEL)
392 api_fatal ("Too many levels of nesting for %s", word);
393 if (insert_file (word, cmd))
394 continue; // There's new stuff in cmd now
397 /* See if we need to allocate more space for argv */
401 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
404 /* Add word to argv file after (optional) wildcard expansion. */
405 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
407 debug_printf ("argv[%d] = '%s'", argc, word);
414 debug_printf ("argc %d", argc);
417 /* sanity and sync check */
419 check_sanity_and_sync (per_process *p)
421 /* Sanity check to make sure developers didn't change the per_process */
422 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
423 /* about changing it]. */
424 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
426 api_fatal ("per_process sanity check failed");
429 /* Make sure that the app and the dll are in sync. */
431 /* Complain if older than last incompatible change */
432 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
433 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
434 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
436 /* magic_biscuit != 0 if using the old style version numbering scheme. */
437 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
438 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
439 p->magic_biscuit, SIZEOF_PER_PROCESS);
441 /* Complain if incompatible API changes made */
442 if (p->api_major > cygwin_version.api_major)
443 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
444 p->api_major, cygwin_version.api_major);
446 if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p->dll_major, p->dll_minor) <=
447 CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK)
448 signal_shift_subtract = 0;
451 child_info NO_COPY *child_proc_info = NULL;
452 static MEMORY_BASIC_INFORMATION NO_COPY sm;
454 #define CYGWIN_GUARD ((wincap.has_page_guard ()) ? \
455 PAGE_EXECUTE_READWRITE|PAGE_GUARD : PAGE_NOACCESS)
458 alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
460 void *new_stack_pointer;
461 MEMORY_BASIC_INFORMATION m;
464 LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;
467 if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)
470 newlen = (LPBYTE) ci->stackbottom - (LPBYTE) curbot;
475 newbase = ci->stacktop;
476 newlen = (DWORD) ci->stackbottom - (DWORD) ci->stacktop;
479 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
480 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
481 ci->stacktop, ci->stackbottom);
483 new_stack_pointer = (void *) ((LPBYTE) ci->stackbottom - ci->stacksize);
485 if (!VirtualAlloc (new_stack_pointer, ci->stacksize, MEM_COMMIT,
486 PAGE_EXECUTE_READWRITE))
487 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
488 new_stack_pointer, ci->stacksize);
489 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
490 api_fatal ("fork: couldn't get new stack info, %E");
493 m.BaseAddress = (LPVOID) ((DWORD) m.BaseAddress - 1);
494 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
496 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
499 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
500 api_fatal ("fork: couldn't get new stack info, %E");
501 ci->stacktop = m.BaseAddress;
505 void *getstack (void *) __attribute__ ((noinline));
507 getstack (volatile char * volatile p)
514 /* extend the stack prior to fork longjmp */
517 alloc_stack (child_info_fork *ci)
519 volatile char * volatile esp;
520 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
521 if (_tlsbase != ci->stackbottom)
522 alloc_stack_hard_way (ci, esp);
525 char *stacktop = (char *) ci->stacktop - 4096;
526 while (_tlstop >= stacktop)
527 esp = getstack (esp);
536 debug_printf ("break here");
543 char buf[CYG_MAX_PATH];
544 if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
550 if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
552 DWORD ms = atoi (buf);
554 len = GetModuleFileName (NULL, buf, CYG_MAX_PATH);
555 console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
557 if (!strace.active && !dynamically_loaded)
563 if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
565 char buf1[CYG_MAX_PATH];
566 len = GetModuleFileName (NULL, buf1, CYG_MAX_PATH);
569 char *p = strpbrk (buf, ":=");
571 p = (char *) "gdb.exe -nw";
574 if (strstr (buf1, buf))
576 error_start_init (p);
578 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
588 get_cygwin_startup_info ()
591 char zeros[sizeof (child_proc_info->zero)] = {0};
593 GetStartupInfo (&si);
594 child_info *res = (child_info *) si.lpReserved2;
595 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
596 || memcmp (res->zero, zeros, sizeof (res->zero)) != 0)
600 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
601 multiple_cygwin_problem ("proc intro", res->intro, 0);
602 else if (res->intro == PROC_MAGIC_GENERIC
603 && res->magic != CHILD_INFO_MAGIC)
604 multiple_cygwin_problem ("proc magic", res->magic,
606 else if (res->cygheap != (void *) &_cygheap_start)
607 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
608 (DWORD) &_cygheap_start);
610 unsigned should_be_cb = 0;
614 user_data->forkee = true;
615 should_be_cb = sizeof (child_info_fork);
620 should_be_cb = sizeof (child_info_spawn);
621 if (should_be_cb != res->cb)
622 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
623 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
624 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
627 system_printf ("unknown exec type %d", res->type);
628 /* intentionally fall through */
641 init_global_security ();
642 lock_process::init ();
643 init_console_handler (TRUE);
644 _impure_ptr = _GLOBAL_REENT;
645 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
646 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
647 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
648 _impure_ptr->_current_locale = "C";
653 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
654 GetCurrentProcess (), &hMainProc, 0, FALSE,
655 DUPLICATE_SAME_ACCESS))
656 hMainProc = GetCurrentProcess ();
658 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
659 &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
660 if (wincap.has_security ())
661 OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
663 SetErrorMode (SEM_FAILCRITICALERRORS);
666 do_global_ctors (&__CTOR_LIST__, 1);
669 child_proc_info = get_cygwin_startup_info ();
670 if (!child_proc_info)
674 cygwin_user_h = child_proc_info->user_h;
675 switch (child_proc_info->type)
678 alloc_stack (fork_info);
679 cygheap_fixup_in_child (false);
686 cygheap_fixup_in_child (true);
688 if (!spawn_info->moreinfo->myself_pinfo ||
689 !DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
690 hMainProc, &h, 0, FALSE,
691 DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
694 if (child_proc_info->type != _PROC_FORK)
695 child_proc_info->ready (true);
696 __argc = spawn_info->moreinfo->argc;
697 __argv = spawn_info->moreinfo->argv;
698 envp = spawn_info->moreinfo->envp;
699 envc = spawn_info->moreinfo->envc;
700 if (!dynamically_loaded)
701 cygheap->fdtab.fixup_after_exec ();
702 signal_fixup_after_exec ();
703 if (spawn_info->moreinfo->old_title)
705 old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
706 cfree (spawn_info->moreinfo->old_title);
714 /* Initialize events */
717 cygheap->cwd.init ();
719 /* Late duplicate simplifies tweaking the process token in uinfo.cc. */
720 if (wincap.has_security ())
721 DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL,
722 SecurityImpersonation, TokenImpersonation,
726 /* Take over from libc's crt0.o and start the application. Note the
727 various special cases when Cygwin DLL is being runtime loaded (as
728 opposed to being link-time loaded by Cygwin apps) from a non
729 cygwin app via LoadLibrary. */
733 /* According to onno@stack.urc.tue.nl, the exception handler record must
735 /* FIXME: Verify forked children get their exception handler set up ok. */
736 exception_list cygwin_except_entry;
738 check_sanity_and_sync (user_data);
742 const int n = 2 * 1024 * 1024;
744 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
747 /* Initialize SIGSEGV handling, etc. */
748 init_exceptions (&cygwin_except_entry);
750 user_data->resourcelocks->Init ();
751 user_data->threadinterface->Init ();
752 ProtectHandle (hMainProc);
753 ProtectHandle (hMainThread);
755 /* Initialize pthread mainthread when not forked and it is safe to call new,
756 otherwise it is reinitalized in fixup_after_fork */
757 if (!user_data->forkee)
758 pthread::init_mainthread ();
761 strace.microseconds ();
764 create_signal_arrived ();
766 /* Initialize debug muto, if DLL is built with --enable-debugging.
767 Need to do this before any helper threads start. */
771 cygheap->fdtab.vfork_child_fixup ();
772 main_vfork = vfork_storage.create ();
775 cygbench ("pre-forkee");
776 if (user_data->forkee)
778 /* If we've played with the stack, stacksize != 0. That means that
779 fork() was invoked from other than the main thread. Make sure that
780 frame pointer is referencing the new stack so that the OS knows what
781 to do when it needs to increase the size of the stack.
783 NOTE: Don't do anything that involves the stack until you've completed
785 if (fork_info->stacksize)
787 _tlsbase = (char *) fork_info->stackbottom;
788 _tlstop = (char *) fork_info->stacktop;
790 longjmp (fork_info->jmp, true);
795 extern void fork_init ();
800 /* Initialize our process table entry. */
801 pinfo_init (envp, envc);
803 /* Can be set only after environment has been initialized. */
804 if (wincap.has_security ())
805 set_cygwin_privileges (hProcImpToken);
807 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
808 old_title = title_buf;
810 /* Allocate cygheap->fdtab */
813 /* Initialize user info. */
816 /* Initialize signal/subprocess handling. */
819 /* Connect to tty. */
824 char *line = GetCommandLineA ();
825 line = strcpy ((char *) alloca (strlen (line) + 1), line);
827 if (current_codepage == oem_cp)
828 CharToOemA (line, line);
830 /* Scan the command line and build argv. Expand wildcards if not
831 called from another cygwin process. */
832 build_argv (line, __argv, __argc,
833 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
835 /* Convert argv[0] to posix rules if it's currently blatantly
837 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
839 char *new_argv0 = (char *) malloc (CYG_MAX_PATH);
840 cygwin_conv_to_posix_path (__argv[0], new_argv0);
841 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
845 __argc_safe = __argc;
846 if (user_data->premain[0])
847 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
848 user_data->premain[i] (__argc, __argv, user_data);
850 /* Set up standard fds in file descriptor table. */
851 cygheap->fdtab.stdio_init ();
853 /* Set up __progname for getopt error call. */
854 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
857 __progname = __argv[0];
860 char *cp = strchr (__progname, '\0') - 4;
861 if (cp > __progname && strcasematch (cp, ".exe"))
865 /* Set new console title if appropriate. */
867 if (display_title && !dynamically_loaded)
869 char *cp = __progname;
870 if (strip_title_path)
871 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
874 set_console_title (cp);
877 cygwin_finished_initializing = true;
878 /* Call init of loaded dlls. */
881 /* Execute any specified "premain" functions */
882 if (user_data->premain[PREMAIN_LEN / 2])
883 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
884 user_data->premain[i] (__argc, __argv, user_data);
886 debug_printf ("user_data->main %p", user_data->main);
888 if (dynamically_loaded)
894 /* Disable case-insensitive globbing */
895 ignore_case_with_glob = false;
901 cygbench (__progname);
903 /* Flush signals and ensure that signal thread is up and running. Can't
904 do this for noncygwin case since the signal thread is blocked due to
905 LoadLibrary serialization. */
906 wait_for_sigthread ();
909 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
913 initialize_main_tls (char *padding)
917 _main_tls = &_my_tls;
918 _main_tls->init_thread (padding, NULL);
920 return &_main_tls->local_clib;
923 /* Wrap the real one, otherwise gdb gets confused about
924 two symbols with the same name, but different addresses.
926 UPTR is a pointer to global data that lives on the libc side of the
927 line [if one distinguishes the application from the dll]. */
929 extern "C" void __stdcall
932 extern HANDLE sync_startup;
933 extern unsigned threadfunc_ix;
936 else if (!sync_startup)
937 system_printf ("internal error: sync_startup not called at start. Expect signal problems.");
940 WaitForSingleObject (sync_startup, INFINITE);
941 CloseHandle (sync_startup);
945 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
947 main_environ = user_data->envptr;
948 *main_environ = NULL;
950 char padding[CYGTLS_PADSIZE];
952 if (child_proc_info && child_proc_info->type == _PROC_FORK)
953 user_data->forkee = true;
955 __sinit (_impure_ptr);
957 initialize_main_tls (padding);
958 dll_crt0_1 (padding);
962 dll_crt0 (per_process *uptr)
964 /* Set the local copy of the pointer into the user space. */
965 if (uptr && uptr != user_data)
967 memcpy (user_data, uptr, per_process_overwrite);
968 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
973 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
974 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
975 calling this function, and that storage must not be overwritten until you
976 unload cygwin1.dll, as it is used for _my_tls. It is best to load
977 cygwin1.dll before spawning any additional threads in your process.
979 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
980 from MSVC and non-cygwin MinGW applications. */
987 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
988 GetCurrentProcess (), &hMainProc, 0, FALSE,
989 DUPLICATE_SAME_ACCESS))
990 hMainProc = GetCurrentProcess ();
992 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
993 &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
994 user_data->magic_biscuit = sizeof (per_process);
996 user_data->envptr = &envp;
997 user_data->fmode_ptr = &_fmode;
999 main_environ = user_data->envptr;
1000 *main_environ = NULL;
1001 initialize_main_tls((char *)&_my_tls);
1008 do_global_ctors (user_data->ctors, false);
1009 atexit (do_global_dtors);
1012 exit_states NO_COPY exit_state;
1015 do_exit (int status)
1017 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1020 vfork_save *vf = vfork_storage.val ();
1021 if (vf != NULL && vf->pid < 0)
1023 exit_state = ES_NOT_EXITING;
1024 vf->restore_exit (status);
1028 lock_process until_exit (true);
1030 if (exit_state < ES_GLOBAL_DTORS)
1032 exit_state = ES_GLOBAL_DTORS;
1033 dll_global_dtors ();
1036 if (exit_state < ES_EVENTS_TERMINATE)
1038 exit_state = ES_EVENTS_TERMINATE;
1039 events_terminate ();
1042 UINT n = (UINT) status;
1043 if (exit_state < ES_THREADTERM)
1045 exit_state = ES_THREADTERM;
1046 cygthread::terminate ();
1049 if (exit_state < ES_SIGNAL)
1051 exit_state = ES_SIGNAL;
1052 signal (SIGCHLD, SIG_IGN);
1053 signal (SIGHUP, SIG_IGN);
1054 signal (SIGINT, SIG_IGN);
1055 signal (SIGQUIT, SIG_IGN);
1058 if (exit_state < ES_CLOSEALL)
1060 exit_state = ES_CLOSEALL;
1064 myself->stopsig = 0;
1066 if (exit_state < ES_HUP_PGRP)
1068 exit_state = ES_HUP_PGRP;
1069 /* Kill orphaned children on group leader exit */
1070 if (myself->has_pgid_children && myself->pid == myself->pgid)
1073 si.si_signo = -SIGHUP;
1074 si.si_code = SI_KERNEL;
1075 si.si_pid = si.si_uid = si.si_errno = 0;
1076 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1077 myself->pid, myself->pgid);
1078 kill_pgrp (myself->pgid, si);
1082 if (exit_state < ES_HUP_SID)
1084 exit_state = ES_HUP_SID;
1085 /* Kill the foreground process group on session leader exit */
1086 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1088 tty *tp = cygwin_shared->tty[myself->ctty];
1089 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1090 myself->pid, myself->sid);
1092 /* CGF FIXME: This can't be right. */
1093 if (tp->getsid () == myself->sid)
1094 tp->kill_pgrp (SIGHUP);
1099 if (exit_state < ES_TITLE)
1101 exit_state = ES_TITLE;
1102 /* restore console title */
1103 if (old_title && display_title)
1104 set_console_title (old_title);
1107 if (exit_state < ES_TTY_TERMINATE)
1109 exit_state = ES_TTY_TERMINATE;
1113 minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n);
1117 static NO_COPY muto atexit_lock;
1120 cygwin_atexit (void (*function)(void))
1123 atexit_lock.init ("atexit_lock");
1124 atexit_lock.acquire ();
1125 res = atexit (function);
1126 atexit_lock.release ();
1133 dll_global_dtors ();
1135 atexit_lock.acquire ();
1142 do_exit (((DWORD) n & 0xff) << 8);
1146 __api_fatal (const char *fmt, ...)
1152 int n = __small_sprintf (buf, "%P (%u): *** ", cygwin_pid (GetCurrentProcessId ()));
1153 __small_vsprintf (buf + n, fmt, ap);
1156 int len = strlen (buf);
1158 WriteFile (GetStdHandle (STD_ERROR_HANDLE), buf, len, &done, 0);
1160 /* Make sure that the message shows up on the screen, too, since this is
1162 if (GetFileType (GetStdHandle (STD_ERROR_HANDLE)) != FILE_TYPE_CHAR)
1164 HANDLE h = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
1165 FILE_SHARE_WRITE | FILE_SHARE_WRITE,
1166 &sec_none, OPEN_EXISTING, 0, 0);
1167 if (h != INVALID_HANDLE_VALUE)
1168 WriteFile (h, buf, len, &done, 0);
1178 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1180 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1182 child_proc_info->type = _PROC_WHOOPS;
1187 if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf, sizeof (buf)))
1190 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1191 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1193 api_fatal ("%s mismatch detected - %p/%p.\n\
1194 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1195 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1196 and delete all but the most recent version. The most recent version *should*\n\
1197 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1198 installed the cygwin distribution. Rebooting is also suggested if you\n\
1199 are unable to find another cygwin DLL.",
1200 what, magic_version, version);
1205 cygbench (const char *s)
1208 if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))
1209 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());