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, 2008 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
13 #include "miscfuncs.h"
22 #include "perprocess.h"
27 #include "child_info_magic.h"
29 #include "shared_info.h"
30 #include "cygwin_version.h"
35 #define MAX_AT_FILE_LEVEL 10
37 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
39 extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
41 HANDLE NO_COPY hMainProc = (HANDLE) -1;
42 HANDLE NO_COPY hMainThread;
43 HANDLE NO_COPY hProcToken;
44 HANDLE NO_COPY hProcImpToken;
46 muto NO_COPY lock_process::locker;
49 bool strip_title_path;
50 bool allow_glob = true;
51 bool NO_COPY in_forkee;
54 int _declspec(dllexport) __argc;
55 char _declspec(dllexport) **__argv;
57 vfork_save NO_COPY *main_vfork;
60 static int NO_COPY envc;
63 extern "C" void __sinit (_reent *);
65 _cygtls NO_COPY *_main_tls;
67 bool NO_COPY cygwin_finished_initializing;
69 MTinterface _mtinterf;
71 bool NO_COPY _cygwin_testing;
73 char NO_COPY almost_null[1];
77 /* This is an exported copy of environ which can be used by DLLs
78 which use cygwin.dll. */
79 char **__cygwin_environ;
80 char ***main_environ = &__cygwin_environ;
81 /* __progname used in getopt error message */
83 struct per_process __cygwin_user_data =
84 {/* initial_sp */ 0, /* magic_biscuit */ 0,
85 /* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
86 /* dll_major */ CYGWIN_VERSION_DLL_MINOR,
87 /* impure_ptr_ptr */ NULL, /* envptr */ NULL,
88 /* malloc */ malloc, /* free */ free,
89 /* realloc */ realloc,
90 /* fmode_ptr */ NULL, /* main */ NULL, /* ctors */ NULL,
91 /* dtors */ NULL, /* data_start */ NULL, /* data_end */ NULL,
92 /* bss_start */ NULL, /* bss_end */ NULL,
94 /* premain */ {NULL, NULL, NULL, NULL},
96 /* unused */ {0, 0, 0, 0, 0, 0, 0},
97 /* UNUSED forkee */ 0,
99 /* api_major */ CYGWIN_VERSION_API_MAJOR,
100 /* api_minor */ CYGWIN_VERSION_API_MINOR,
101 /* unused2 */ {0, 0, 0, 0, 0, 0},
102 /* threadinterface */ &_mtinterf,
103 /* impure_ptr */ _GLOBAL_REENT,
105 bool ignore_case_with_glob;
106 int __declspec (dllexport) _check_for_executable = true;
112 int NO_COPY __api_fatal_exit_val = 1;
114 char title_buf[TITLESIZE + 1];
119 void (**pfunc) () = user_data->dtors;
122 user_data->dtors = NULL;
128 static void __stdcall
129 do_global_ctors (void (**in_pfunc)(), int force)
131 if (!force && in_forkee)
132 return; // inherit constructed stuff from parent pid
134 /* Run ctors backwards, so skip the first entry and find how many
135 there are, then run them. */
137 void (**pfunc) () = in_pfunc;
141 while (--pfunc > in_pfunc)
146 * Replaces @file in the command line with the contents of the file.
147 * There may be multiple @file's in a single command line
148 * A \@file is replaced with @file so that echo \@foo would print
149 * @foo and not the contents of foo.
151 static bool __stdcall
152 insert_file (char *name, char *&cmd)
158 PWCHAR wname = tp.w_get ();
159 sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
160 f = CreateFileW (wname,
161 GENERIC_READ, /* open for reading */
162 FILE_SHARE_READ, /* share for reading */
163 &sec_none_nih, /* default security */
164 OPEN_EXISTING, /* existing file only */
165 FILE_ATTRIBUTE_NORMAL,/* normal file */
166 NULL); /* no attr. template */
168 if (f == INVALID_HANDLE_VALUE)
170 debug_printf ("couldn't open file '%s', %E", name);
174 /* This only supports files up to about 4 billion bytes in
175 size. I am making the bold assumption that this is big
176 enough for this feature */
177 size = GetFileSize (f, NULL);
178 if (size == 0xFFFFFFFF)
180 debug_printf ("couldn't get file size for '%s', %E", name);
184 int new_size = strlen (cmd) + size + 2;
185 char *tmp = (char *) malloc (new_size);
188 debug_printf ("malloc failed, %E");
192 /* realloc passed as it should */
195 rf_result = ReadFile (f, tmp, size, &rf_read, NULL);
197 if (!rf_result || (rf_read != size))
199 debug_printf ("ReadFile failed, %E");
204 strcpy (tmp + size, cmd);
213 return ch == '"' || ch == '\'';
216 /* Step over a run of characters delimited by quotes */
217 static /*__inline*/ char *
218 quoted (char *cmd, int winshell)
226 strcpy (cmd, cmd + 1);
227 if (*(p = strechr (cmd, quote)))
232 const char *s = quote == '\'' ? "'" : "\\\"";
233 /* This must have been run from a Windows shell, so preserve
234 quotes for globify to play with later. */
235 while (*cmd && *++cmd)
236 if ((p = strpbrk (cmd, s)) == NULL)
238 cmd = strchr (cmd, '\0'); // no closing quote
243 else if (quote == '"' && p[1] == '"')
246 cmd = ++p; // a quoted quote
250 cmd = p + 1; // point to after end
256 /* Perform a glob on word if it contains wildcard characters.
257 Also quote every character between quotes to force glob to
258 treat the characters literally. */
260 globify (char *word, char **&argv, int &argc, int &argvlen)
262 if (*word != '~' && strpbrk (word, "?*[\"\'(){}") == NULL)
267 int dos_spec = isdrive (word);
268 if (!dos_spec && isquote (*word) && word[1] && word[2])
269 dos_spec = isdrive (word + 1);
271 /* We'll need more space if there are quoting characters in
272 word. If that is the case, doubling the size of the
273 string should provide more than enough space. */
274 if (strpbrk (word, "'\""))
276 char pattern[strlen (word) + ((dos_spec + 1) * n) + 1];
278 /* Fill pattern with characters from word, quoting any
279 characters found within quotes. */
280 for (p = pattern, s = word; *s != '\000'; s++, p++)
283 if (dos_spec && *s == '\\')
290 while (*++s && *s != quote)
292 if (dos_spec || *s != '\\')
294 else if (s[1] == quote || s[1] == '\\')
310 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
311 if (glob (pattern, GLOB_TILDE | GLOB_NOCHECK | GLOB_BRACE | GLOB_QUOTE, NULL, &gl) || !gl.gl_pathc)
314 /* Allocate enough space in argv for the matched filenames. */
316 if ((argc += gl.gl_pathc) > argvlen)
319 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
322 /* Copy the matched filenames to argv. */
323 char **gv = gl.gl_pathv;
324 char **av = argv + n;
327 debug_printf ("argv[%d] = '%s'", n++, *gv);
331 /* Clean up after glob. */
336 /* Build argv, argc from string passed from Windows. */
338 static void __stdcall
339 build_argv (char *cmd, char **&argv, int &argc, int winshell)
342 int nesting = 0; // monitor "nesting" from insert_file
348 /* Scan command line until there is nothing left. */
358 /* Found the beginning of an argument. */
360 char *sawquote = NULL;
363 if (*cmd != '"' && (!winshell || *cmd != '\''))
364 cmd++; // Skip over this character
366 /* Skip over characters until the closing quote */
369 cmd = quoted (cmd, winshell && argc > 0);
371 if (issep (*cmd)) // End of argument if space
375 *cmd++ = '\0'; // Terminate `word'
377 /* Possibly look for @file construction assuming that this isn't
378 the very first argument and the @ wasn't quoted */
379 if (argc && sawquote != word && *word == '@')
381 if (++nesting > MAX_AT_FILE_LEVEL)
382 api_fatal ("Too many levels of nesting for %s", word);
383 if (insert_file (word, cmd))
384 continue; // There's new stuff in cmd now
387 /* See if we need to allocate more space for argv */
391 argv = (char **) realloc (argv, (1 + argvlen) * sizeof (argv[0]));
394 /* Add word to argv file after (optional) wildcard expansion. */
395 if (!winshell || !argc || !globify (word, argv, argc, argvlen))
397 debug_printf ("argv[%d] = '%s'", argc, word);
404 debug_printf ("argc %d", argc);
407 /* sanity and sync check */
409 check_sanity_and_sync (per_process *p)
411 /* Sanity check to make sure developers didn't change the per_process */
412 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
413 /* about changing it]. */
414 if (sizeof (per_process) != SIZEOF_PER_PROCESS)
415 api_fatal ("per_process sanity check failed");
417 /* Make sure that the app and the dll are in sync. */
419 /* Complain if older than last incompatible change */
420 if (p->dll_major < CYGWIN_VERSION_DLL_EPOCH)
421 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
422 p->dll_major, CYGWIN_VERSION_DLL_EPOCH);
424 /* magic_biscuit != 0 if using the old style version numbering scheme. */
425 if (p->magic_biscuit != SIZEOF_PER_PROCESS)
426 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
427 p->magic_biscuit, SIZEOF_PER_PROCESS);
429 /* Complain if incompatible API changes made */
430 if (p->api_major > cygwin_version.api_major)
431 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
432 p->api_major, cygwin_version.api_major);
435 child_info NO_COPY *child_proc_info = NULL;
437 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
440 child_info_fork::alloc_stack_hard_way (volatile char *b)
442 void *new_stack_pointer;
443 MEMORY_BASIC_INFORMATION m;
448 if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
449 api_fatal ("fork: couldn't get stack info, %E");
451 LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
453 if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
456 newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
461 newbase = (LPBYTE) stacktop - (128 * 1024);
462 newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
466 if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
467 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
468 stacktop, stackbottom);
469 new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
470 if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
471 PAGE_EXECUTE_READWRITE))
472 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
473 new_stack_pointer, stacksize);
474 if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
475 api_fatal ("fork: couldn't get new stack info, %E");
479 m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
480 if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
482 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
485 if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
486 api_fatal ("fork: couldn't get new stack info, %E");
487 stacktop = m.BaseAddress;
491 void *getstack (void *) __attribute__ ((noinline));
493 getstack (volatile char * volatile p)
500 /* extend the stack prior to fork longjmp */
503 child_info_fork::alloc_stack ()
505 volatile char * volatile esp;
506 __asm__ volatile ("movl %%esp,%0": "=r" (esp));
507 if (_tlsbase != stackbottom)
508 alloc_stack_hard_way (esp);
511 char *st = (char *) stacktop - 4096;
512 while (_tlstop >= st)
513 esp = getstack (esp);
521 static int NO_COPY sent_break;
524 debug_printf ("break here");
530 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
534 char buf[NT_MAX_PATH];
537 if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
539 DWORD ms = atoi (buf);
540 console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
542 if (!strace.active () && !dynamically_loaded)
545 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
547 char buf1[NT_MAX_PATH];
548 len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
551 char *p = strpbrk (buf, ":=");
553 p = (char *) "gdb.exe -nw";
556 if (strstr (buf1, buf))
558 error_start_init (p);
560 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
569 get_cygwin_startup_info ()
573 GetStartupInfo (&si);
574 child_info *res = (child_info *) si.lpReserved2;
576 if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
577 || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
581 if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
582 multiple_cygwin_problem ("proc intro", res->intro, 0);
583 else if (res->cygheap != (void *) &_cygheap_start)
584 multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
585 (DWORD) &_cygheap_start);
587 unsigned should_be_cb = 0;
592 should_be_cb = sizeof (child_info_fork);
597 should_be_cb = sizeof (child_info_spawn);
598 if (should_be_cb != res->cb)
599 multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
600 else if (sizeof (fhandler_union) != res->fhandler_union_cb)
601 multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
602 if (res->isstraced ())
605 for (unsigned i = 0; !being_debugged () && i < 10000; i++)
606 low_priority_sleep (0);
611 system_printf ("unknown exec type %d", res->type);
612 /* intentionally fall through */
622 #define dll_data_start &_data_start__
623 #define dll_data_end &_data_end__
624 #define dll_bss_start &_bss_start__
625 #define dll_bss_end &_bss_end__
628 child_info_fork::handle_fork ()
630 cygheap_fixup_in_child (false);
633 myself->uid = cygheap->user.real_uid;
634 myself->gid = cygheap->user.real_gid;
636 child_copy (parent, false,
637 "dll data", dll_data_start, dll_data_end,
638 "dll bss", dll_bss_start, dll_bss_end,
639 "user heap", cygheap->user_heap.base, cygheap->user_heap.ptr,
641 /* step 2 now that the dll has its heap filled in, we can fill in the
642 user's data and bss since user_data is now filled out. */
643 child_copy (parent, false,
644 "data", user_data->data_start, user_data->data_end,
645 "bss", user_data->bss_start, user_data->bss_end,
648 if (fixup_mmaps_after_fork (parent))
649 api_fatal ("recreate_mmaps_after_fork_failed");
653 child_info_spawn::handle_spawn ()
655 extern void fixup_lockf_after_exec ();
657 cygheap_fixup_in_child (true);
659 if (!moreinfo->myself_pinfo ||
660 !DuplicateHandle (hMainProc, moreinfo->myself_pinfo, hMainProc, &h, 0,
661 FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
664 __argc = moreinfo->argc;
665 __argv = moreinfo->argv;
666 envp = moreinfo->envp;
667 envc = moreinfo->envc;
668 if (!dynamically_loaded)
669 cygheap->fdtab.fixup_after_exec ();
671 cygheap->fdtab.move_fd (__stdin, 0);
673 cygheap->fdtab.move_fd (__stdout, 1);
677 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
678 handles might get confused. */
679 CloseHandle (child_proc_info->parent);
680 child_proc_info->parent = NULL;
682 signal_fixup_after_exec ();
683 if (moreinfo->old_title)
685 old_title = strcpy (title_buf, moreinfo->old_title);
686 cfree (moreinfo->old_title);
688 fixup_lockf_after_exec ();
694 init_global_security ();
697 SetErrorMode (SEM_FAILCRITICALERRORS);
699 /* Initialize signal processing here, early, in the hopes that the creation
700 of a thread early in the process will cause more predictability in memory
701 layout for the main thread. */
704 lock_process::init ();
705 _impure_ptr = _GLOBAL_REENT;
706 _impure_ptr->_stdin = &_impure_ptr->__sf[0];
707 _impure_ptr->_stdout = &_impure_ptr->__sf[1];
708 _impure_ptr->_stderr = &_impure_ptr->__sf[2];
709 _impure_ptr->_current_locale = "C";
710 user_data->impure_ptr = _impure_ptr;
711 user_data->impure_ptr_ptr = &_impure_ptr;
713 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
714 GetCurrentProcess (), &hMainProc, 0, FALSE,
715 DUPLICATE_SAME_ACCESS))
716 hMainProc = GetCurrentProcess ();
718 DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
719 &hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
721 OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
722 set_cygwin_privileges (hProcToken);
725 do_global_ctors (&__CTOR_LIST__, 1);
728 child_proc_info = get_cygwin_startup_info ();
729 if (!child_proc_info)
733 cygwin_user_h = child_proc_info->user_h;
734 switch (child_proc_info->type)
737 fork_info->handle_fork ();
741 spawn_info->handle_spawn ();
746 user_data->threadinterface->Init ();
750 /* Initialize events */
752 tty_list::init_session ();
754 cygheap->cwd.init ();
756 debug_printf ("finished dll_crt0_0 initialization");
759 /* Take over from libc's crt0.o and start the application. Note the
760 various special cases when Cygwin DLL is being runtime loaded (as
761 opposed to being link-time loaded by Cygwin apps) from a non
762 cygwin app via LoadLibrary. */
766 check_sanity_and_sync (user_data);
770 const int n = 2 * 1024 * 1024;
772 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
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 (); /* FIXME: move into wait_sig? */
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;
812 _my_tls.init_exception_handler (_cygtls::handle_exceptions);
815 longjmp (fork_info->jmp, true);
820 extern void fork_init ();
824 pinfo_init (envp, envc);
826 if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
827 old_title = title_buf;
829 /* Allocate cygheap->fdtab */
832 uinfo_init (); /* initialize user info */
834 wait_for_sigthread ();
835 extern DWORD threadfunc_ix;
837 system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
839 /* Connect to tty. */
840 tty::init_session ();
844 PWCHAR wline = GetCommandLineW ();
845 size_t size = sys_wcstombs (NULL, 0, wline);
846 char *line = (char *) alloca (size);
847 sys_wcstombs (line, size, wline);
849 /* Scan the command line and build argv. Expand wildcards if not
850 called from another cygwin process. */
851 build_argv (line, __argv, __argc,
852 NOTSTATE (myself, PID_CYGPARENT) && allow_glob);
854 /* Convert argv[0] to posix rules if it's currently blatantly
856 if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
858 char *new_argv0 = (char *) malloc (NT_MAX_PATH);
859 cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
860 new_argv0, NT_MAX_PATH);
861 __argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
865 __argc_safe = __argc;
866 if (user_data->premain[0])
867 for (unsigned int i = 0; i < PREMAIN_LEN / 2; i++)
868 user_data->premain[i] (__argc, __argv, user_data);
870 /* Set up standard fds in file descriptor table. */
871 cygheap->fdtab.stdio_init ();
873 /* Set up __progname for getopt error call. */
874 if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
877 __progname = __argv[0];
880 char *cp = strchr (__progname, '\0') - 4;
881 if (cp > __progname && ascii_strcasematch (cp, ".exe"))
885 /* Set new console title if appropriate. */
887 if (display_title && !dynamically_loaded)
889 char *cp = __progname;
890 if (strip_title_path)
891 for (char *ptr = cp; *ptr && *ptr != ' '; ptr++)
894 set_console_title (cp);
897 cygwin_finished_initializing = true;
898 /* Call init of loaded dlls. */
901 /* Execute any specified "premain" functions */
902 if (user_data->premain[PREMAIN_LEN / 2])
903 for (unsigned int i = PREMAIN_LEN / 2; i < PREMAIN_LEN; i++)
904 user_data->premain[i] (__argc, __argv, user_data);
906 debug_printf ("user_data->main %p", user_data->main);
908 if (dynamically_loaded)
914 /* Disable case-insensitive globbing */
915 ignore_case_with_glob = false;
920 cygbench (__progname);
922 /* Flush signals and ensure that signal thread is up and running. Can't
923 do this for noncygwin case since the signal thread is blocked due to
924 LoadLibrary serialization. */
927 cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
930 extern "C" void __stdcall
933 main_environ = user_data->envptr;
935 fork_info->alloc_stack ();
937 __sinit (_impure_ptr);
939 _main_tls = &_my_tls;
940 _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
944 dll_crt0 (per_process *uptr)
946 /* Set the local copy of the pointer into the user space. */
947 if (!in_forkee && uptr && uptr != user_data)
949 memcpy (user_data, uptr, per_process_overwrite);
950 *(user_data->impure_ptr_ptr) = _GLOBAL_REENT;
955 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll.
956 You must have CYGTLS_PADSIZE bytes reserved at the bottom of the stack
957 calling this function, and that storage must not be overwritten until you
958 unload cygwin1.dll, as it is used for _my_tls. It is best to load
959 cygwin1.dll before spawning any additional threads in your process.
961 See winsup/testsuite/cygload for an example of how to use cygwin1.dll
962 from MSVC and non-cygwin MinGW applications. */
969 user_data->magic_biscuit = sizeof (per_process);
971 user_data->envptr = &envp;
972 user_data->fmode_ptr = &_fmode;
980 do_global_ctors (user_data->ctors, false);
981 atexit (do_global_dtors);
984 exit_states NO_COPY exit_state;
989 syscall_printf ("do_exit (%d), exit_state %d", status, exit_state);
992 vfork_save *vf = vfork_storage.val ();
993 if (vf != NULL && vf->pid < 0)
995 exit_state = ES_NOT_EXITING;
996 vf->restore_exit (status);
1000 lock_process until_exit (true);
1002 if (exit_state < ES_GLOBAL_DTORS)
1004 exit_state = ES_GLOBAL_DTORS;
1005 dll_global_dtors ();
1008 if (exit_state < ES_EVENTS_TERMINATE)
1010 exit_state = ES_EVENTS_TERMINATE;
1011 events_terminate ();
1014 UINT n = (UINT) status;
1015 if (exit_state < ES_THREADTERM)
1017 exit_state = ES_THREADTERM;
1018 cygthread::terminate ();
1021 if (exit_state < ES_SIGNAL)
1023 exit_state = ES_SIGNAL;
1024 signal (SIGCHLD, SIG_IGN);
1025 signal (SIGHUP, SIG_IGN);
1026 signal (SIGINT, SIG_IGN);
1027 signal (SIGQUIT, SIG_IGN);
1030 if (exit_state < ES_CLOSEALL)
1032 exit_state = ES_CLOSEALL;
1036 myself->stopsig = 0;
1038 if (exit_state < ES_HUP_PGRP)
1040 exit_state = ES_HUP_PGRP;
1041 /* Kill orphaned children on group leader exit */
1042 if (myself->has_pgid_children && myself->pid == myself->pgid)
1045 si.si_signo = -SIGHUP;
1046 si.si_code = SI_KERNEL;
1047 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1048 myself->pid, myself->pgid);
1049 kill_pgrp (myself->pgid, si);
1053 if (exit_state < ES_HUP_SID)
1055 exit_state = ES_HUP_SID;
1056 /* Kill the foreground process group on session leader exit */
1057 if (getpgrp () > 0 && myself->pid == myself->sid && real_tty_attached (myself))
1059 tty *tp = cygwin_shared->tty[myself->ctty];
1060 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1061 myself->pid, myself->sid);
1063 /* CGF FIXME: This can't be right. */
1064 if (tp->getsid () == myself->sid)
1065 tp->kill_pgrp (SIGHUP);
1070 if (exit_state < ES_TITLE)
1072 exit_state = ES_TITLE;
1073 /* restore console title */
1074 if (old_title && display_title)
1075 set_console_title (old_title);
1078 if (exit_state < ES_TTY_TERMINATE)
1080 exit_state = ES_TTY_TERMINATE;
1081 cygwin_shared->tty.terminate ();
1087 static NO_COPY muto atexit_lock;
1090 cygwin_atexit (void (*function)(void))
1093 atexit_lock.init ("atexit_lock");
1094 atexit_lock.acquire ();
1095 res = atexit (function);
1096 atexit_lock.release ();
1103 dll_global_dtors ();
1105 atexit_lock.acquire ();
1112 do_exit (((DWORD) n & 0xff) << 8);
1116 __api_fatal (const char *fmt, ...)
1122 int n = __small_sprintf (buf, "%P: *** fatal error - ");
1123 __small_vsprintf (buf + n, fmt, ap);
1125 strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
1130 myself.exit (__api_fatal_exit_val);
1134 multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
1136 if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
1138 child_proc_info->type = _PROC_WHOOPS;
1142 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
1145 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
1146 system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
1148 api_fatal ("%s mismatch detected - %p/%p.\n\
1149 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1150 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1151 and delete all but the most recent version. The most recent version *should*\n\
1152 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1153 installed the cygwin distribution. Rebooting is also suggested if you\n\
1154 are unable to find another cygwin DLL.",
1155 what, magic_version, version);
1160 cygbench (const char *s)
1162 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
1163 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());