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"
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)
429 api_fatal ("per_process sanity check failed");
432 /* Make sure that the app and the dll are in sync. */
434 /* Complain if older than last incompatible change */
435 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
436 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
437 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
439 /* magic_biscuit != 0 if using the old style version numbering scheme. */
440 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
441 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
442 p->magic_biscuit, SIZEOF_PER_PROCESS);
444 /* Complain if incompatible API changes made */
445 if (p->api_major > cygwin_version.api_major)
446 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
447 p->api_major, cygwin_version.api_major);
449 if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p->dll_major, p->dll_minor) <=
450 CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK)
451 signal_shift_subtract = 0;
454 child_info NO_COPY *child_proc_info = NULL;
456 #define CYGWIN_GUARD ((wincap.has_page_guard ()) ? \
457 PAGE_EXECUTE_READWRITE|PAGE_GUARD : PAGE_NOACCESS)
460 child_info_fork::alloc_stack_hard_way (volatile char *b)
462 void *new_stack_pointer;
463 MEMORY_BASIC_INFORMATION m;
468 if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
469 api_fatal ("fork: couldn't get stack info, %E");
471 LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
473 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
476 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
482 newlen = (DWORD) stackbottom - (DWORD) stacktop;
485 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
486 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
487 stacktop, stackbottom);
489 new_stack_pointer = (void *) ((LPBYTE) stackbottom - stacksize);
490 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
491 PAGE_EXECUTE_READWRITE))
492 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
493 new_stack_pointer, stacksize);
494 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
495 api_fatal ("fork: couldn't get new stack info, %E");
498 m.BaseAddress = (LPVOID) ((DWORD) m.BaseAddress - 1);
499 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
501 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
504 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
505 api_fatal ("fork: couldn't get new stack info, %E");
506 stacktop = m.BaseAddress;
510 void *getstack (void *) __attribute__ ((noinline));
512 getstack (volatile char * volatile p)
519 /* extend the stack prior to fork longjmp */
522 child_info_fork::alloc_stack ()
524 volatile char * volatile esp;
525 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
526 if (_tlsbase != stackbottom)
527 alloc_stack_hard_way (esp);
530 char *st = (char *) stacktop - 4096;
531 while (_tlstop >= st)
532 esp = getstack (esp);
541 debug_printf ("break here");
548 char buf[CYG_MAX_PATH];
549 if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
555 if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
557 DWORD ms = atoi (buf);
559 len = GetModuleFileName (NULL, buf, CYG_MAX_PATH);
560 console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
562 if (!strace.active () && !dynamically_loaded)
565 if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
567 char buf1[CYG_MAX_PATH];
568 len = GetModuleFileName (NULL, buf1, CYG_MAX_PATH);
571 char *p = strpbrk (buf, ":=");
573 p = (char *) "gdb.exe -nw";
576 if (strstr (buf1, buf))
578 error_start_init (p);
580 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
590 get_cygwin_startup_info ()
593 char zeros[sizeof (child_proc_info->zero)] = {0};
595 GetStartupInfo (&si);
596 child_info *res = (child_info *) si.lpReserved2;
597 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
598 || memcmp (res->zero, zeros, sizeof (res->zero)) != 0)
602 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
603 multiple_cygwin_problem ("proc intro", res->intro, 0);
604 else if (res->intro == PROC_MAGIC_GENERIC
605 && res->magic != CHILD_INFO_MAGIC)
606 multiple_cygwin_problem ("proc magic", res->magic,
608 else if (res->cygheap != (void *) &_cygheap_start)
609 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
610 (DWORD) &_cygheap_start);
612 unsigned should_be_cb = 0;
617 should_be_cb = sizeof (child_info_fork);
622 should_be_cb = sizeof (child_info_spawn);
623 if (should_be_cb != res->cb)
624 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
625 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
626 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
627 if (res->isstraced ())
630 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
631 low_priority_sleep (0);
636 system_printf ("unknown exec type %d", res->type);
637 /* intentionally fall through */
647 #define dll_data_start &_data_start__
648 #define dll_data_end &_data_end__
649 #define dll_bss_start &_bss_start__
650 #define dll_bss_end &_bss_end__
653 child_info_fork::handle_fork ()
655 cygheap_fixup_in_child (false);
658 myself->uid = cygheap->user.real_uid;
659 myself->gid = cygheap->user.real_gid;
661 child_copy (parent, false,
662 "dll data", dll_data_start, dll_data_end,
663 "dll bss", dll_bss_start, dll_bss_end,
664 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
666 /* step 2 now that the dll has its heap filled in, we can fill in the
667 user's data and bss since user_data is now filled out. */
668 child_copy (parent, false,
669 "data", user_data->data_start, user_data->data_end,
670 "bss", user_data->bss_start, user_data->bss_end,
673 if (fixup_mmaps_after_fork (parent))
674 api_fatal ("recreate_mmaps_after_fork_failed");
678 child_info_spawn::handle_spawn ()
681 cygheap_fixup_in_child (true);
683 if (!moreinfo->myself_pinfo ||
684 !DuplicateHandle (hMainProc, moreinfo->myself_pinfo, hMainProc, &h, 0,
685 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
689 __argc = moreinfo->argc;
690 __argv = moreinfo->argv;
691 envp = moreinfo->envp;
692 envc = moreinfo->envc;
693 if (!dynamically_loaded)
694 cygheap->fdtab.fixup_after_exec ();
695 signal_fixup_after_exec ();
696 if (moreinfo->old_title)
698 old_title = strcpy (title_buf, moreinfo->old_title);
699 cfree (moreinfo->old_title);
706 init_global_security ();
709 SetErrorMode (SEM_FAILCRITICALERRORS);
711 /* Initialize signal processing here, early, in the hopes that the creation
712 of a thread early in the process will cause more predictability in memory
713 layout for the main thread. */
716 lock_process::init ();
717 _impure_ptr = _GLOBAL_REENT;
718 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
719 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
720 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
721 _impure_ptr->_current_locale = "C";
722 user_data->impure_ptr = _impure_ptr;
723 user_data->impure_ptr_ptr = &_impure_ptr;
726 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
727 GetCurrentProcess (), &hMainProc, 0, FALSE,
728 DUPLICATE_SAME_ACCESS))
729 hMainProc = GetCurrentProcess ();
731 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
732 &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
733 if (wincap.has_security ())
734 OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
737 do_global_ctors (&__CTOR_LIST__, 1);
740 child_proc_info = get_cygwin_startup_info ();
741 if (!child_proc_info)
745 cygwin_user_h = child_proc_info->user_h;
746 switch (child_proc_info->type)
749 fork_info->handle_fork ();
753 spawn_info->handle_spawn ();
758 user_data->resourcelocks->Init ();
759 user_data->threadinterface->Init ();
763 /* Initialize events */
766 cygheap->cwd.init ();
768 /* Late duplicate simplifies tweaking the process token in uinfo.cc. */
769 if (wincap.has_security ()
770 && !DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL,
771 SecurityImpersonation, TokenImpersonation,
774 system_printf ("DuplicateTokenEx failed, %E");
779 debug_printf ("finished dll_crt0_0 initialization");
782 /* Take over from libc's crt0.o and start the application. Note the
783 various special cases when Cygwin DLL is being runtime loaded (as
784 opposed to being link-time loaded by Cygwin apps) from a non
785 cygwin app via LoadLibrary. */
789 check_sanity_and_sync (user_data);
793 const int n = 2 * 1024 * 1024;
795 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
798 ProtectHandle (hMainProc);
799 ProtectHandle (hMainThread);
801 /* Initialize pthread mainthread when not forked and it is safe to call new,
802 otherwise it is reinitalized in fixup_after_fork */
804 pthread::init_mainthread ();
807 strace.microseconds ();
810 create_signal_arrived (); /* FIXME: move into wait_sig? */
812 /* Initialize debug muto, if DLL is built with --enable-debugging.
813 Need to do this before any helper threads start. */
817 cygheap->fdtab.vfork_child_fixup ();
818 main_vfork = vfork_storage.create ();
821 cygbench ("pre-forkee");
824 /* If we've played with the stack, stacksize != 0. That means that
825 fork() was invoked from other than the main thread. Make sure that
826 frame pointer is referencing the new stack so that the OS knows what
827 to do when it needs to increase the size of the stack.
829 NOTE: Don't do anything that involves the stack until you've completed
831 if (fork_info->stacksize)
833 _tlsbase = (char *) fork_info->stackbottom;
834 _tlstop = (char *) fork_info->stacktop;
836 longjmp (fork_info->jmp, true);
841 extern void fork_init ();
845 pinfo_init (envp, envc);
847 /* Can be set only after environment has been initialized. */
848 if (wincap.has_security ())
849 set_cygwin_privileges (hProcImpToken);
851 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
852 old_title = title_buf;
854 /* Allocate cygheap->fdtab */
857 uinfo_init (); /* initialize user info */
859 wait_for_sigthread ();
860 extern DWORD threadfunc_ix;
862 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
865 /* Connect to tty. */
870 char *line = GetCommandLineA ();
871 line = strcpy ((char *) alloca (strlen (line) + 1), line);
873 if (current_codepage == oem_cp)
874 CharToOemA (line, line);
876 /* Scan the command line and build argv. Expand wildcards if not
877 called from another cygwin process. */
878 build_argv (line, __argv, __argc,
879 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
881 /* Convert argv[0] to posix rules if it's currently blatantly
883 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
885 char *new_argv0 = (char *) malloc (CYG_MAX_PATH);
886 cygwin_conv_to_posix_path (__argv[0], new_argv0);
887 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
891 __argc_safe = __argc;
892 if (user_data->premain[0])
893 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
894 user_data->premain[i] (__argc, __argv, user_data);
896 /* Set up standard fds in file descriptor table. */
897 cygheap->fdtab.stdio_init ();
899 /* Set up __progname for getopt error call. */
900 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
903 __progname = __argv[0];
906 char *cp = strchr (__progname, '\0') - 4;
907 if (cp > __progname && strcasematch (cp, ".exe"))
911 /* Set new console title if appropriate. */
913 if (display_title && !dynamically_loaded)
915 char *cp = __progname;
916 if (strip_title_path)
917 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
920 set_console_title (cp);
923 cygwin_finished_initializing = true;
924 /* Call init of loaded dlls. */
927 /* Execute any specified "premain" functions */
928 if (user_data->premain[PREMAIN_LEN / 2])
929 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
930 user_data->premain[i] (__argc, __argv, user_data);
932 debug_printf ("user_data->main %p", user_data->main);
934 if (dynamically_loaded)
940 /* Disable case-insensitive globbing */
941 ignore_case_with_glob = false;
946 cygbench (__progname);
948 /* Flush signals and ensure that signal thread is up and running. Can't
949 do this for noncygwin case since the signal thread is blocked due to
950 LoadLibrary serialization. */
953 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
957 initialize_main_tls (char *padding)
961 _main_tls = &_my_tls;
962 _main_tls->init_thread (padding, NULL);
967 /* Wrap the real one, otherwise gdb gets confused about
968 two symbols with the same name, but different addresses.
970 UPTR is a pointer to global data that lives on the libc side of the
971 line [if one distinguishes the application from the dll]. */
973 extern "C" void __stdcall
976 main_environ = user_data->envptr;
978 char padding[CYGTLS_PADSIZE];
981 fork_info->alloc_stack ();
983 __sinit (_impure_ptr);
985 initialize_main_tls (padding);
986 dll_crt0_1 (padding);
990 dll_crt0 (per_process *uptr)
992 /* Set the local copy of the pointer into the user space. */
993 if (!in_forkee && uptr && uptr != user_data)
995 memcpy (user_data, uptr, per_process_overwrite);
996 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
1001 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
1002 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
1003 calling this function, and that storage must not be overwritten until you
1004 unload cygwin1.dll, as it is used for _my_tls. It is best to load
1005 cygwin1.dll before spawning any additional threads in your process.
1007 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
1008 from MSVC and non-cygwin MinGW applications. */
1015 user_data->magic_biscuit = sizeof (per_process);
1017 user_data->envptr = &envp;
1018 user_data->fmode_ptr = &_fmode;
1026 do_global_ctors (user_data->ctors, false);
1027 atexit (do_global_dtors);
1030 exit_states NO_COPY exit_state;
1033 do_exit (int status)
1035 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
1038 vfork_save *vf = vfork_storage.val ();
1039 if (vf != NULL && vf->pid < 0)
1041 exit_state = ES_NOT_EXITING;
1042 vf->restore_exit (status);
1046 lock_process until_exit (true);
1048 if (exit_state < ES_GLOBAL_DTORS)
1050 exit_state = ES_GLOBAL_DTORS;
1051 dll_global_dtors ();
1054 if (exit_state < ES_EVENTS_TERMINATE)
1056 exit_state = ES_EVENTS_TERMINATE;
1057 events_terminate ();
1060 UINT n = (UINT) status;
1061 if (exit_state < ES_THREADTERM)
1063 exit_state = ES_THREADTERM;
1064 cygthread::terminate ();
1067 if (exit_state < ES_SIGNAL)
1069 exit_state = ES_SIGNAL;
1070 signal (SIGCHLD, SIG_IGN);
1071 signal (SIGHUP, SIG_IGN);
1072 signal (SIGINT, SIG_IGN);
1073 signal (SIGQUIT, SIG_IGN);
1076 if (exit_state < ES_CLOSEALL)
1078 exit_state = ES_CLOSEALL;
1082 myself->stopsig = 0;
1084 if (exit_state < ES_HUP_PGRP)
1086 exit_state = ES_HUP_PGRP;
1087 /* Kill orphaned children on group leader exit */
1088 if (myself->has_pgid_children && myself->pid == myself->pgid)
1091 si.si_signo = -SIGHUP;
1092 si.si_code = SI_KERNEL;
1093 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1094 myself->pid, myself->pgid);
1095 kill_pgrp (myself->pgid, si);
1099 if (exit_state < ES_HUP_SID)
1101 exit_state = ES_HUP_SID;
1102 /* Kill the foreground process group on session leader exit */
1103 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1105 tty *tp = cygwin_shared->tty[myself->ctty];
1106 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1107 myself->pid, myself->sid);
1109 /* CGF FIXME: This can't be right. */
1110 if (tp->getsid () == myself->sid)
1111 tp->kill_pgrp (SIGHUP);
1116 if (exit_state < ES_TITLE)
1118 exit_state = ES_TITLE;
1119 /* restore console title */
1120 if (old_title && display_title)
1121 set_console_title (old_title);
1124 if (exit_state < ES_TTY_TERMINATE)
1126 exit_state = ES_TTY_TERMINATE;
1133 static NO_COPY muto atexit_lock;
1136 cygwin_atexit (void (*function)(void))
1139 atexit_lock.init ("atexit_lock");
1140 atexit_lock.acquire ();
1141 res = atexit (function);
1142 atexit_lock.release ();
1149 dll_global_dtors ();
1151 atexit_lock.acquire ();
1158 do_exit (((DWORD) n & 0xff) << 8);
1162 __api_fatal (const char *fmt, ...)
1168 int n = __small_sprintf (buf, "%P: *** fatal error - ", cygwin_pid (GetCurrentProcessId ()));
1169 __small_vsprintf (buf + n, fmt, ap);
1171 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1176 myself.exit (__api_fatal_exit_val);
1180 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1182 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1184 child_proc_info->type = _PROC_WHOOPS;
1189 if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf, sizeof (buf)))
1192 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1193 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1195 api_fatal ("%s mismatch detected - %p/%p.\n\
1196 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1197 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1198 and delete all but the most recent version. The most recent version *should*\n\
1199 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1200 installed the cygwin distribution. Rebooting is also suggested if you\n\
1201 are unable to find another cygwin DLL.",
1202 what, magic_version, version);
1207 cygbench (const char *s)
1210 if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))
1211 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());