1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
7 This file is part of Cygwin.
9 This software is a copyrighted work licensed under the terms of the
10 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
14 #include "miscfuncs.h"
25 #include "perprocess.h"
30 #include "child_info_magic.h"
32 #include "shared_info.h"
33 #include "cygwin_version.h"
37 #include "exception.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
));
46 extern "C" void __sinit (_reent
*);
48 static int NO_COPY envc
;
49 static char NO_COPY
**envp
;
51 static char title_buf
[TITLESIZE
+ 1];
53 bool NO_COPY jit_debug
;
58 void (**pfunc
) () = user_data
->dtors
;
61 user_data
->dtors
= NULL
;
68 do_global_ctors (void (**in_pfunc
)(), int force
)
70 if (!force
&& in_forkee
)
71 return; // inherit constructed stuff from parent pid
73 /* Run ctors backwards, so skip the first entry and find how many
74 there are, then run them. */
76 void (**pfunc
) () = in_pfunc
;
80 while (--pfunc
> in_pfunc
)
85 * Replaces @file in the command line with the contents of the file.
86 * There may be multiple @file's in a single command line
87 * A \@file is replaced with @file so that echo \@foo would print
88 * @foo and not the contents of foo.
91 insert_file (char *name
, char *&cmd
)
97 PWCHAR wname
= tp
.w_get ();
98 sys_mbstowcs (wname
, NT_MAX_PATH
, name
+ 1);
99 f
= CreateFileW (wname
,
100 GENERIC_READ
, /* open for reading */
101 FILE_SHARE_READ
, /* share for reading */
102 &sec_none_nih
, /* default security */
103 OPEN_EXISTING
, /* existing file only */
104 FILE_ATTRIBUTE_NORMAL
,/* normal file */
105 NULL
); /* no attr. template */
107 if (f
== INVALID_HANDLE_VALUE
)
109 debug_printf ("couldn't open file '%s', %E", name
);
113 /* This only supports files up to about 4 billion bytes in
114 size. I am making the bold assumption that this is big
115 enough for this feature */
116 size
= GetFileSize (f
, NULL
);
117 if (size
== 0xFFFFFFFF)
119 debug_printf ("couldn't get file size for '%s', %E", name
);
123 int new_size
= strlen (cmd
) + size
+ 2;
124 char *tmp
= (char *) malloc (new_size
);
127 debug_printf ("malloc failed, %E");
131 /* realloc passed as it should */
134 rf_result
= ReadFile (f
, tmp
, size
, &rf_read
, NULL
);
136 if (!rf_result
|| (rf_read
!= size
))
138 debug_printf ("ReadFile failed, %E");
143 strcpy (tmp
+ size
, cmd
);
152 return ch
== '"' || ch
== '\'';
155 /* Step over a run of characters delimited by quotes */
156 static /*__inline*/ char *
157 quoted (char *cmd
, int winshell
)
165 strcpy (cmd
, cmd
+ 1);
166 if (*(p
= strechr (cmd
, quote
)))
171 const char *s
= quote
== '\'' ? "'" : "\\\"";
172 /* This must have been run from a Windows shell, so preserve
173 quotes for globify to play with later. */
174 while (*cmd
&& *++cmd
)
175 if ((p
= strpbrk (cmd
, s
)) == NULL
)
177 cmd
= strchr (cmd
, '\0'); // no closing quote
182 else if (quote
== '"' && p
[1] == '"')
185 cmd
= ++p
; // a quoted quote
189 cmd
= p
+ 1; // point to after end
195 /* Perform a glob on word if it contains wildcard characters.
196 Also quote every character between quotes to force glob to
197 treat the characters literally. */
199 globify (char *word
, char **&argv
, int &argc
, int &argvlen
)
201 if (*word
!= '~' && strpbrk (word
, "?*[\"\'(){}") == NULL
)
206 int dos_spec
= isdrive (word
);
207 if (!dos_spec
&& isquote (*word
) && word
[1] && word
[2])
208 dos_spec
= isdrive (word
+ 1);
210 /* We'll need more space if there are quoting characters in
211 word. If that is the case, doubling the size of the
212 string should provide more than enough space. */
213 if (strpbrk (word
, "'\""))
215 char pattern
[strlen (word
) + ((dos_spec
+ 1) * n
) + 1];
217 /* Fill pattern with characters from word, quoting any
218 characters found within quotes. */
219 for (p
= pattern
, s
= word
; *s
!= '\000'; s
++, p
++)
222 if (dos_spec
&& *s
== '\\')
229 while (*++s
&& *s
!= quote
)
231 if (dos_spec
|| *s
!= '\\')
233 else if (s
[1] == quote
|| s
[1] == '\\')
236 size_t cnt
= isascii (*s
) ? 1 : mbtowc (NULL
, s
, MB_CUR_MAX
);
237 if (cnt
<= 1 || cnt
== (size_t)-1)
257 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
258 if (glob (pattern
, GLOB_TILDE
| GLOB_NOCHECK
| GLOB_BRACE
| GLOB_QUOTE
, NULL
, &gl
) || !gl
.gl_pathc
)
261 /* Allocate enough space in argv for the matched filenames. */
263 if ((argc
+= gl
.gl_pathc
) > argvlen
)
266 argv
= (char **) realloc (argv
, (1 + argvlen
) * sizeof (argv
[0]));
269 /* Copy the matched filenames to argv. */
270 char **gv
= gl
.gl_pathv
;
271 char **av
= argv
+ n
;
274 debug_printf ("argv[%d] = '%s'", n
++, *gv
);
278 /* Clean up after glob. */
283 /* Build argv, argc from string passed from Windows. */
285 static void __stdcall
286 build_argv (char *cmd
, char **&argv
, int &argc
, int winshell
)
289 int nesting
= 0; // monitor "nesting" from insert_file
295 /* Scan command line until there is nothing left. */
305 /* Found the beginning of an argument. */
307 char *sawquote
= NULL
;
310 if (*cmd
!= '"' && (!winshell
|| *cmd
!= '\''))
311 cmd
++; // Skip over this character
313 /* Skip over characters until the closing quote */
316 cmd
= quoted (cmd
, winshell
&& argc
> 0);
318 if (issep (*cmd
)) // End of argument if space
322 *cmd
++ = '\0'; // Terminate `word'
324 /* Possibly look for @file construction assuming that this isn't
325 the very first argument and the @ wasn't quoted */
326 if (argc
&& sawquote
!= word
&& *word
== '@')
328 if (++nesting
> MAX_AT_FILE_LEVEL
)
329 api_fatal ("Too many levels of nesting for %s", word
);
330 if (insert_file (word
, cmd
))
331 continue; // There's new stuff in cmd now
334 /* See if we need to allocate more space for argv */
338 argv
= (char **) realloc (argv
, (1 + argvlen
) * sizeof (argv
[0]));
341 /* Add word to argv file after (optional) wildcard expansion. */
342 if (!winshell
|| !argc
|| !globify (word
, argv
, argc
, argvlen
))
344 debug_printf ("argv[%d] = '%s'", argc
, word
);
351 debug_printf ("argc %d", argc
);
354 /* sanity and sync check */
356 check_sanity_and_sync (per_process
*p
)
358 /* Sanity check to make sure developers didn't change the per_process */
359 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
360 /* about changing it]. */
361 if (sizeof (per_process
) != SIZEOF_PER_PROCESS
)
362 api_fatal ("per_process sanity check failed");
364 /* Make sure that the app and the dll are in sync. */
366 /* Complain if older than last incompatible change */
367 if (p
->dll_major
< CYGWIN_VERSION_DLL_EPOCH
)
368 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
369 p
->dll_major
, CYGWIN_VERSION_DLL_EPOCH
);
371 /* magic_biscuit != 0 if using the old style version numbering scheme. */
372 if (p
->magic_biscuit
!= SIZEOF_PER_PROCESS
)
373 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
374 p
->magic_biscuit
, SIZEOF_PER_PROCESS
);
376 /* Complain if incompatible API changes made */
377 if (p
->api_major
> cygwin_version
.api_major
)
378 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
379 p
->api_major
, cygwin_version
.api_major
);
381 /* This is a kludge to work around a version of _cygwin_common_crt0
382 which overwrote the cxx_malloc field with the local DLL copy.
383 Hilarity ensues if the DLL is not loaded while the process
385 __cygwin_user_data
.cxx_malloc
= &default_cygwin_cxx_malloc
;
388 child_info NO_COPY
*child_proc_info
= NULL
;
390 #define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
393 child_info_fork::alloc_stack_hard_way (volatile char *b
)
395 void *new_stack_pointer
;
396 MEMORY_BASIC_INFORMATION m
;
401 if (!VirtualQuery ((LPCVOID
) &b
, &m
, sizeof m
))
402 api_fatal ("fork: couldn't get stack info, %E");
404 LPBYTE curbot
= (LPBYTE
) m
.BaseAddress
+ m
.RegionSize
;
406 if (stacktop
> (LPBYTE
) m
.AllocationBase
&& stacktop
< curbot
)
409 newlen
= (LPBYTE
) stackbottom
- (LPBYTE
) curbot
;
414 newbase
= (LPBYTE
) stacktop
- (128 * 1024);
415 newlen
= (LPBYTE
) stackbottom
- (LPBYTE
) newbase
;
419 if (!VirtualAlloc (newbase
, newlen
, MEM_RESERVE
, PAGE_NOACCESS
))
420 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
421 stacktop
, stackbottom
);
422 new_stack_pointer
= (void *) ((LPBYTE
) stackbottom
- (stacksize
+= 8192));
423 if (!VirtualAlloc (new_stack_pointer
, stacksize
, MEM_COMMIT
,
424 PAGE_EXECUTE_READWRITE
))
425 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
426 new_stack_pointer
, stacksize
);
427 if (!VirtualQuery ((LPCVOID
) new_stack_pointer
, &m
, sizeof m
))
428 api_fatal ("fork: couldn't get new stack info, %E");
432 m
.BaseAddress
= (LPBYTE
) m
.BaseAddress
- 1;
433 if (!VirtualAlloc ((LPVOID
) m
.BaseAddress
, 1, MEM_COMMIT
,
435 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
438 if (!VirtualQuery ((LPCVOID
) m
.BaseAddress
, &m
, sizeof m
))
439 api_fatal ("fork: couldn't get new stack info, %E");
440 stacktop
= m
.BaseAddress
;
444 void *getstack (void *) __attribute__ ((noinline
));
446 getstack (volatile char * volatile p
)
453 /* extend the stack prior to fork longjmp */
456 child_info_fork::alloc_stack ()
458 volatile char * volatile esp
;
459 __asm__
volatile ("movl %%esp,%0": "=r" (esp
));
460 if (_tlsbase
!= stackbottom
)
461 alloc_stack_hard_way (esp
);
464 char *st
= (char *) stacktop
- 4096;
465 while (_tlstop
>= st
)
466 esp
= getstack (esp
);
474 static int NO_COPY sent_break
;
477 debug_printf ("break here");
483 if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL
, 0))
487 char buf
[NT_MAX_PATH
];
490 if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf
, sizeof (buf
) - 1))
492 DWORD ms
= atoi (buf
);
493 console_printf ("Sleeping %d, pid %u %P\n", ms
, GetCurrentProcessId ());
495 if (!strace
.active () && !dynamically_loaded
)
498 if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf
, sizeof (buf
) - 1))
500 char buf1
[NT_MAX_PATH
];
501 len
= GetModuleFileName (NULL
, buf1
, NT_MAX_PATH
);
504 char *p
= strpbrk (buf
, ":=");
506 p
= (char *) "gdb.exe -nw";
509 if (strstr (buf1
, buf
))
511 error_start_init (p
);
514 console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
523 get_cygwin_startup_info ()
527 GetStartupInfo (&si
);
528 child_info
*res
= (child_info
*) si
.lpReserved2
;
530 if (si
.cbReserved2
< EXEC_MAGIC_SIZE
|| !res
531 || res
->intro
!= PROC_MAGIC_GENERIC
|| res
->magic
!= CHILD_INFO_MAGIC
)
535 if ((res
->intro
& OPROC_MAGIC_MASK
) == OPROC_MAGIC_GENERIC
)
536 multiple_cygwin_problem ("proc intro", res
->intro
, 0);
537 else if (res
->cygheap
!= (void *) &_cygheap_start
)
538 multiple_cygwin_problem ("cygheap base", (DWORD
) res
->cygheap
,
539 (DWORD
) &_cygheap_start
);
541 unsigned should_be_cb
= 0;
546 should_be_cb
= sizeof (child_info_fork
);
551 should_be_cb
= sizeof (child_info_spawn
);
552 if (should_be_cb
!= res
->cb
)
553 multiple_cygwin_problem ("proc size", res
->cb
, should_be_cb
);
554 else if (sizeof (fhandler_union
) != res
->fhandler_union_cb
)
555 multiple_cygwin_problem ("fhandler size", res
->fhandler_union_cb
, sizeof (fhandler_union
));
556 if (res
->isstraced ())
559 for (unsigned i
= 0; !being_debugged () && i
< 10000; i
++)
565 system_printf ("unknown exec type %d", res
->type
);
566 /* intentionally fall through */
576 #define dll_data_start &_data_start__
577 #define dll_data_end &_data_end__
578 #define dll_bss_start &_bss_start__
579 #define dll_bss_end &_bss_end__
582 child_info_fork::handle_fork ()
584 cygheap_fixup_in_child (false);
586 myself
.thisproc (NULL
);
587 myself
->uid
= cygheap
->user
.real_uid
;
588 myself
->gid
= cygheap
->user
.real_gid
;
590 child_copy (parent
, false,
591 "dll data", dll_data_start
, dll_data_end
,
592 "dll bss", dll_bss_start
, dll_bss_end
,
593 "user heap", cygheap
->user_heap
.base
, cygheap
->user_heap
.ptr
,
596 /* Do the relocations here. These will actually likely be overwritten by the
597 below child_copy but we do them here in case there is a read-only section
598 which does not get copied by fork. */
599 _pei386_runtime_relocator (user_data
);
601 /* step 2 now that the dll has its heap filled in, we can fill in the
602 user's data and bss since user_data is now filled out. */
603 child_copy (parent
, false,
604 "data", user_data
->data_start
, user_data
->data_end
,
605 "bss", user_data
->bss_start
, user_data
->bss_end
,
608 if (fixup_mmaps_after_fork (parent
))
609 api_fatal ("recreate_mmaps_after_fork_failed");
613 child_info_spawn::handle_spawn ()
615 extern void fixup_lockf_after_exec ();
617 cygheap_fixup_in_child (true);
619 if (!moreinfo
->myself_pinfo
||
620 !DuplicateHandle (GetCurrentProcess (), moreinfo
->myself_pinfo
,
621 GetCurrentProcess (), &h
, 0,
622 FALSE
, DUPLICATE_SAME_ACCESS
| DUPLICATE_CLOSE_SOURCE
))
625 __argc
= moreinfo
->argc
;
626 __argv
= moreinfo
->argv
;
627 envp
= moreinfo
->envp
;
628 envc
= moreinfo
->envc
;
629 if (!dynamically_loaded
)
630 cygheap
->fdtab
.fixup_after_exec ();
632 cygheap
->fdtab
.move_fd (__stdin
, 0);
634 cygheap
->fdtab
.move_fd (__stdout
, 1);
635 cygheap
->user
.groups
.clear_supp ();
639 /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
640 handles might get confused. */
641 CloseHandle (child_proc_info
->parent
);
642 child_proc_info
->parent
= NULL
;
644 signal_fixup_after_exec ();
645 if (moreinfo
->old_title
)
647 old_title
= strcpy (title_buf
, moreinfo
->old_title
);
648 cfree (moreinfo
->old_title
);
650 fixup_lockf_after_exec ();
654 /* Setting the TS-aware flag in the application's PE header is sufficient.
655 Just keep this in as a reminder. */
657 static DEP_SYSTEM_POLICY_TYPE dep_system_policy
= (DEP_SYSTEM_POLICY_TYPE
) -1;
665 if (dep_system_policy
< 0)
667 dep_system_policy
= GetSystemDEPPolicy ();
668 debug_printf ("DEP System Policy: %d", (int) dep_system_policy
);
670 if (dep_system_policy
< OptIn
)
672 if (!GetProcessDEPPolicy (GetCurrentProcess (), &ppolicy
, &perm
))
674 debug_printf ("GetProcessDEPPolicy: %E");
677 debug_printf ("DEP Process Policy: %d (permanent = %d)", ppolicy
, perm
);
678 if (ppolicy
> 0 && !perm
&& !SetProcessDEPPolicy (0))
679 debug_printf ("SetProcessDEPPolicy: %E");
683 /* Retrieve and store system directory for later use. Note that the
684 directory is stored with a trailing backslash! */
686 init_windows_system_directory ()
688 windows_system_directory_length
=
689 GetSystemDirectoryW (windows_system_directory
, MAX_PATH
);
690 if (windows_system_directory_length
== 0)
691 api_fatal ("can't find windows system directory");
692 windows_system_directory
[windows_system_directory_length
++] = L
'\\';
693 windows_system_directory
[windows_system_directory_length
] = L
'\0';
699 init_windows_system_directory ();
700 init_global_security ();
703 SetErrorMode (SEM_FAILCRITICALERRORS
| SEM_NOGPFAULTERRORBOX
);
705 lock_process::init ();
706 _impure_ptr
= _GLOBAL_REENT
;
707 _impure_ptr
->_stdin
= &_impure_ptr
->__sf
[0];
708 _impure_ptr
->_stdout
= &_impure_ptr
->__sf
[1];
709 _impure_ptr
->_stderr
= &_impure_ptr
->__sf
[2];
710 _impure_ptr
->_current_locale
= "C";
711 user_data
->impure_ptr
= _impure_ptr
;
712 user_data
->impure_ptr_ptr
= &_impure_ptr
;
714 DuplicateHandle (GetCurrentProcess (), GetCurrentThread (),
715 GetCurrentProcess (), &hMainThread
,
716 0, false, DUPLICATE_SAME_ACCESS
);
718 OpenProcessToken (GetCurrentProcess (), MAXIMUM_ALLOWED
, &hProcToken
);
719 set_cygwin_privileges (hProcToken
);
722 do_global_ctors (&__CTOR_LIST__
, 1);
725 child_proc_info
= get_cygwin_startup_info ();
726 if (!child_proc_info
)
730 cygwin_user_h
= child_proc_info
->user_h
;
731 switch (child_proc_info
->type
)
734 fork_info
->handle_fork ();
738 spawn_info
->handle_spawn ();
743 user_data
->threadinterface
->Init ();
747 /* Initialize events */
749 tty_list::init_session ();
752 /* Setting the TS-aware flag in the application's PE header is sufficient.
753 Just keep this in as a reminder. */
755 /* The disable_dep function disables DEP for all Cygwin processes if
756 the process runs on a Windows Server 2008 with Terminal Services
757 installed. This combination (TS+DEP) breaks *some* Cygwin
758 applications. The Terminal Service specific DLL tsappcmp.dll
759 changes the page protection of some pages in the application's text
760 segment from PAGE_EXECUTE_WRITECOPY to PAGE_WRITECOPY for no
761 apparent reason. This occurs before any Cygwin or applicaton code
762 had a chance to run. MS has no explanation for this so far, but is
763 rather busy trying to avoid giving support for this problem (as of
766 Unfortunately disabling DEP seems to have a not negligible
767 performance hit. In the long run, either MS has to fix their
768 problem, or we have to find a better workaround, if any exists.
769 Idle idea: Adding EXECUTE protection to all text segment pages? */
770 if (wincap
.ts_has_dep_problem ())
774 /* Initialize signal processing here, early, in the hopes that the creation
775 of a thread early in the process will cause more predictability in memory
776 layout for the main thread. */
777 if (!wincap
.has_buggy_thread_startup () && !dynamically_loaded
)
780 debug_printf ("finished dll_crt0_0 initialization");
783 /* Take over from libc's crt0.o and start the application. Note the
784 various special cases when Cygwin DLL is being runtime loaded (as
785 opposed to being link-time loaded by Cygwin apps) from a non
786 cygwin app via LoadLibrary. */
790 extern void initial_setlocale ();
792 if (wincap
.has_buggy_thread_startup () || dynamically_loaded
)
794 check_sanity_and_sync (user_data
);
796 /* Initialize malloc and then call user_shared_initialize since it relies
797 on a functioning malloc and it's possible that the user's program may
798 have overridden malloc. We only know about that at this stage,
801 user_shared
->initialize ();
805 const int n
= 2 * 1024 * 1024;
807 small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR
, n
));
810 ProtectHandle (hMainThread
);
812 cygheap
->cwd
.init ();
814 /* Initialize pthread mainthread when not forked and it is safe to call new,
815 otherwise it is reinitalized in fixup_after_fork */
818 pthread::init_mainthread ();
819 _pei386_runtime_relocator (user_data
);
823 strace
.microseconds ();
826 create_signal_arrived (); /* FIXME: move into wait_sig? */
828 /* Initialize debug muto, if DLL is built with --enable-debugging.
829 Need to do this before any helper threads start. */
833 cygheap
->fdtab
.vfork_child_fixup ();
834 main_vfork
= vfork_storage
.create ();
837 cygbench ("pre-forkee");
840 /* If we've played with the stack, stacksize != 0. That means that
841 fork() was invoked from other than the main thread. Make sure that
842 frame pointer is referencing the new stack so that the OS knows what
843 to do when it needs to increase the size of the stack.
845 NOTE: Don't do anything that involves the stack until you've completed
847 if (fork_info
->stacksize
)
849 _tlsbase
= (char *) fork_info
->stackbottom
;
850 _tlstop
= (char *) fork_info
->stacktop
;
853 longjmp (fork_info
->jmp
, true);
856 __sinit (_impure_ptr
);
860 extern void fork_init ();
864 pinfo_init (envp
, envc
);
866 if (!old_title
&& GetConsoleTitle (title_buf
, TITLESIZE
))
867 old_title
= title_buf
;
869 /* Allocate cygheap->fdtab */
872 uinfo_init (); /* initialize user info */
874 /* Connect to tty. */
875 tty::init_session ();
877 /* Set internal locale to the environment settings. */
878 initial_setlocale ();
882 PWCHAR wline
= GetCommandLineW ();
883 size_t size
= sys_wcstombs (NULL
, 0, wline
);
884 char *line
= (char *) alloca (size
);
885 sys_wcstombs (line
, size
, wline
);
887 /* Scan the command line and build argv. Expand wildcards if not
888 called from another cygwin process. */
889 build_argv (line
, __argv
, __argc
,
890 NOTSTATE (myself
, PID_CYGPARENT
) && allow_glob
);
892 /* Convert argv[0] to posix rules if it's currently blatantly
894 if ((strchr (__argv
[0], ':')) || (strchr (__argv
[0], '\\')))
896 char *new_argv0
= (char *) malloc (NT_MAX_PATH
);
897 cygwin_conv_path (CCP_WIN_A_TO_POSIX
| CCP_RELATIVE
, __argv
[0],
898 new_argv0
, NT_MAX_PATH
);
899 __argv
[0] = (char *) realloc (new_argv0
, strlen (new_argv0
) + 1);
903 __argc_safe
= __argc
;
904 if (user_data
->premain
[0])
905 for (unsigned int i
= 0; i
< PREMAIN_LEN
/ 2; i
++)
906 user_data
->premain
[i
] (__argc
, __argv
, user_data
);
908 /* Set up standard fds in file descriptor table. */
909 cygheap
->fdtab
.stdio_init ();
911 /* Set up __progname for getopt error call. */
912 if (__argv
[0] && (__progname
= strrchr (__argv
[0], '/')))
915 __progname
= __argv
[0];
918 char *cp
= strchr (__progname
, '\0') - 4;
919 if (cp
> __progname
&& ascii_strcasematch (cp
, ".exe"))
923 /* Set new console title if appropriate. */
925 if (display_title
&& !dynamically_loaded
)
927 char *cp
= __progname
;
928 if (strip_title_path
)
929 for (char *ptr
= cp
; *ptr
&& *ptr
!= ' '; ptr
++)
932 set_console_title (cp
);
935 (void) xdr_set_vprintf (&cygxdr_vwarnx
);
936 cygwin_finished_initializing
= true;
937 /* Call init of loaded dlls. */
940 /* Execute any specified "premain" functions */
941 if (user_data
->premain
[PREMAIN_LEN
/ 2])
942 for (unsigned int i
= PREMAIN_LEN
/ 2; i
< PREMAIN_LEN
; i
++)
943 user_data
->premain
[i
] (__argc
, __argv
, user_data
);
947 if (dynamically_loaded
)
950 /* Disable case-insensitive globbing */
951 ignore_case_with_glob
= false;
954 cygbench (__progname
);
957 /* Per POSIX set the default application locale back to "C". */
958 _setlocale_r (_REENT
, LC_CTYPE
, "C");
961 cygwin_exit (user_data
->main (__argc
, __argv
, *user_data
->envptr
));
963 .global __cygwin_exit_return \n\
964 __cygwin_exit_return: \n\
968 extern "C" void __stdcall
971 main_environ
= user_data
->envptr
;
973 fork_info
->alloc_stack ();
975 _main_tls
= &_my_tls
;
976 _main_tls
->call ((DWORD (*) (void *, void *)) dll_crt0_1
, NULL
);
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 /* Ordering is critical here. DLL ctors have already been
1017 run as they were being loaded, so we should stack the
1018 queued call to DLL dtors now. */
1019 atexit (dll_global_dtors
);
1020 do_global_ctors (user_data
->ctors
, false);
1021 /* Now we have run global ctors, register their dtors.
1023 At exit, global dtors will run first, so the app can still
1024 use shared library functions while terminating; then the
1025 DLLs will be destroyed; finally newlib will shut down stdio
1026 and terminate itself. */
1027 atexit (do_global_dtors
);
1028 sig_dispatch_pending (true);
1032 do_exit (int status
)
1034 syscall_printf ("do_exit (%d), exit_state %d", status
, exit_state
);
1037 vfork_save
*vf
= vfork_storage
.val ();
1038 if (vf
!= NULL
&& vf
->pid
< 0)
1040 exit_state
= ES_NOT_EXITING
;
1041 vf
->restore_exit (status
);
1045 lock_process
until_exit (true);
1047 if (exit_state
< ES_EVENTS_TERMINATE
)
1049 exit_state
= ES_EVENTS_TERMINATE
;
1050 events_terminate ();
1053 UINT n
= (UINT
) status
;
1054 if (exit_state
< ES_THREADTERM
)
1056 exit_state
= ES_THREADTERM
;
1057 cygthread::terminate ();
1060 if (exit_state
< ES_SIGNAL
)
1062 exit_state
= ES_SIGNAL
;
1063 signal (SIGCHLD
, SIG_IGN
);
1064 signal (SIGHUP
, SIG_IGN
);
1065 signal (SIGINT
, SIG_IGN
);
1066 signal (SIGQUIT
, SIG_IGN
);
1069 if (exit_state
< ES_CLOSEALL
)
1071 exit_state
= ES_CLOSEALL
;
1075 myself
->stopsig
= 0;
1077 if (exit_state
< ES_HUP_PGRP
)
1079 exit_state
= ES_HUP_PGRP
;
1080 /* Kill orphaned children on group leader exit */
1081 if (myself
->has_pgid_children
&& myself
->pid
== myself
->pgid
)
1084 si
.si_signo
= -SIGHUP
;
1085 si
.si_code
= SI_KERNEL
;
1086 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1087 myself
->pid
, myself
->pgid
);
1088 kill_pgrp (myself
->pgid
, si
);
1092 if (exit_state
< ES_HUP_SID
)
1094 exit_state
= ES_HUP_SID
;
1095 /* Kill the foreground process group on session leader exit */
1096 if (getpgrp () > 0 && myself
->pid
== myself
->sid
&& real_tty_attached (myself
))
1098 tty
*tp
= cygwin_shared
->tty
[myself
->ctty
];
1099 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1100 myself
->pid
, myself
->sid
);
1102 /* CGF FIXME: This can't be right. */
1103 if (tp
->getsid () == myself
->sid
)
1104 tp
->kill_pgrp (SIGHUP
);
1109 if (exit_state
< ES_TITLE
)
1111 exit_state
= ES_TITLE
;
1112 /* restore console title */
1113 if (old_title
&& display_title
)
1114 set_console_title (old_title
);
1117 if (exit_state
< ES_TTY_TERMINATE
)
1119 exit_state
= ES_TTY_TERMINATE
;
1120 cygwin_shared
->tty
.terminate ();
1127 cygwin_atexit (void (*fn
) (void))
1130 dll
*d
= dlls
.find ((void *) _my_tls
.retaddr ());
1131 res
= d
? __cxa_atexit ((void (*) (void *)) fn
, NULL
, d
) : atexit (fn
);
1138 exit_state
= ES_EXIT_STARTING
;
1145 do_exit (((DWORD
) n
& 0xff) << 8);
1148 extern "C" void cygwin_stackdump ();
1151 __api_fatal (const char *fmt
, ...)
1157 int n
= __small_sprintf (buf
, "%P: *** fatal error - ");
1158 __small_vsprintf (buf
+ n
, fmt
, ap
);
1160 strace
.prntf (_STRACE_SYSTEM
, NULL
, "%s", buf
);
1165 cygwin_stackdump ();
1166 myself
.exit (__api_fatal_exit_val
);
1170 multiple_cygwin_problem (const char *what
, unsigned magic_version
, unsigned version
)
1172 if (_cygwin_testing
&& (strstr (what
, "proc") || strstr (what
, "cygheap")))
1174 child_proc_info
->type
= _PROC_WHOOPS
;
1178 if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL
, 0))
1181 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version
) == version
)
1182 system_printf ("%s magic number mismatch detected - %p/%p", what
, magic_version
, version
);
1184 api_fatal ("%s mismatch detected - %p/%p.\n\
1185 This problem is probably due to using incompatible versions of the cygwin DLL.\n\
1186 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1187 and delete all but the most recent version. The most recent version *should*\n\
1188 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1189 installed the cygwin distribution. Rebooting is also suggested if you\n\
1190 are unable to find another cygwin DLL.",
1191 what
, magic_version
, version
);
1196 cygbench (const char *s
)
1198 if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL
, 0))
1199 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s
, strace
.microseconds ());