1 /* dcrt0.cc -- essentially the main() for the Cygwin dll
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003 Red Hat, Inc.
5 This file is part of Cygwin.
7 This software is a copyrighted work licensed under the terms of the
8 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
15 #include "exceptions.h"
24 #include "perprocess.h"
30 #include "child_info_magic.h"
31 #include "perthread.h"
32 #include "shared_info.h"
33 #include "cygwin_version.h"
35 #include "cygthread.h"
38 #define MAX_AT_FILE_LEVEL 10
40 #define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
42 HANDLE NO_COPY hMainProc
;
43 HANDLE NO_COPY hMainThread
;
45 sigthread NO_COPY mainthread
; // ID of the main thread
47 per_thread_waitq NO_COPY waitq_storage
;
48 per_thread_vfork NO_COPY vfork_storage
;
49 per_thread_signal_dispatch NO_COPY signal_dispatch_storage
;
51 per_thread NO_COPY
*threadstuff
[] = {&waitq_storage
,
53 &signal_dispatch_storage
,
57 bool strip_title_path
;
58 bool allow_glob
= TRUE
;
59 codepage_type current_codepage
= ansi_cp
;
61 int cygwin_finished_initializing
;
63 /* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
64 This is subtracted from the signal number prior to shifting the bit.
65 In older versions of cygwin, the signal was used as-is to shift the
66 bit for masking. So, we'll temporarily detect this and set it to zero
67 for programs that are linked using older cygwins. This is just a stopgap
68 measure to allow an orderly transfer to the new, correct sigmask method. */
69 unsigned NO_COPY
int signal_shift_subtract
= 1;
71 ResourceLocks _reslock NO_COPY
;
72 MTinterface _mtinterf
;
74 bool NO_COPY _cygwin_testing
;
75 unsigned NO_COPY _cygwin_testing_magic
;
77 char NO_COPY almost_null
[1];
81 /* This is an exported copy of environ which can be used by DLLs
82 which use cygwin.dll. */
83 char **__cygwin_environ
;
85 /* __progname used in getopt error message */
87 struct _reent reent_data
= _REENT_INIT(reent_data
);
88 struct per_process __cygwin_user_data
=
89 {/* initial_sp */ 0, /* magic_biscuit */ 0,
90 /* dll_major */ CYGWIN_VERSION_DLL_MAJOR
,
91 /* dll_major */ CYGWIN_VERSION_DLL_MINOR
,
92 /* impure_ptr_ptr */ NULL
, /* envptr */ NULL
,
93 /* malloc */ malloc
, /* free */ free
,
94 /* realloc */ realloc
,
95 /* fmode_ptr */ NULL
, /* main */ NULL
, /* ctors */ NULL
,
96 /* dtors */ NULL
, /* data_start */ NULL
, /* data_end */ NULL
,
97 /* bss_start */ NULL
, /* bss_end */ NULL
,
99 /* premain */ {NULL
, NULL
, NULL
, NULL
},
101 /* unused */ {0, 0, 0, 0, 0, 0, 0},
104 /* api_major */ CYGWIN_VERSION_API_MAJOR
,
105 /* api_minor */ CYGWIN_VERSION_API_MINOR
,
106 /* unused2 */ {0, 0, 0, 0, 0},
107 /* resourcelocks */ &_reslock
, /* threadinterface */ &_mtinterf
,
108 /* impure_ptr */ &reent_data
,
110 bool ignore_case_with_glob
;
111 int __declspec (dllexport
) _check_for_executable
= TRUE
;
118 char title_buf
[TITLESIZE
+ 1];
121 do_global_dtors (void)
123 if (user_data
->dtors
)
125 void (**pfunc
)() = user_data
->dtors
;
131 static void __stdcall
132 do_global_ctors (void (**in_pfunc
)(), int force
)
136 if (user_data
->forkee
|| user_data
->run_ctors_p
)
137 return; // inherit constructed stuff from parent pid
138 user_data
->run_ctors_p
= 1;
141 /* Run ctors backwards, so skip the first entry and find how many
142 there are, then run them. */
144 void (**pfunc
)() = in_pfunc
;
148 while (--pfunc
> in_pfunc
)
151 if (user_data
->magic_biscuit
== SIZEOF_PER_PROCESS
)
152 atexit (do_global_dtors
);
156 * Replaces @file in the command line with the contents of the file.
157 * There may be multiple @file's in a single command line
158 * A \@file is replaced with @file so that echo \@foo would print
159 * @foo and not the contents of foo.
162 insert_file (char *name
, char *&cmd
)
167 f
= CreateFile (name
+ 1,
168 GENERIC_READ
, /* open for reading */
169 FILE_SHARE_READ
, /* share for reading */
170 &sec_none_nih
, /* no security */
171 OPEN_EXISTING
, /* existing file only */
172 FILE_ATTRIBUTE_NORMAL
, /* normal file */
173 NULL
); /* no attr. template */
175 if (f
== INVALID_HANDLE_VALUE
)
177 debug_printf ("couldn't open file '%s', %E", name
);
181 /* This only supports files up to about 4 billion bytes in
182 size. I am making the bold assumption that this is big
183 enough for this feature */
184 size
= GetFileSize (f
, NULL
);
185 if (size
== 0xFFFFFFFF)
187 debug_printf ("couldn't get file size for '%s', %E", name
);
191 int new_size
= strlen (cmd
) + size
+ 2;
192 char *tmp
= (char *) malloc (new_size
);
195 debug_printf ("malloc failed, %E");
199 /* realloc passed as it should */
202 rf_result
= ReadFile (f
, tmp
, size
, &rf_read
, NULL
);
204 if (!rf_result
|| (rf_read
!= size
))
206 debug_printf ("ReadFile failed, %E");
211 strcpy (tmp
+ size
, cmd
);
220 return ch
== '"' || ch
== '\'';
223 /* Step over a run of characters delimited by quotes */
224 static /*__inline*/ char *
225 quoted (char *cmd
, int winshell
)
233 strcpy (cmd
, cmd
+ 1);
234 if (*(p
= strechr (cmd
, quote
)))
239 const char *s
= quote
== '\'' ? "'" : "\\\"";
240 /* This must have been run from a Windows shell, so preserve
241 quotes for globify to play with later. */
242 while (*cmd
&& *++cmd
)
243 if ((p
= strpbrk (cmd
, s
)) == NULL
)
245 cmd
= strchr (cmd
, '\0'); // no closing quote
250 else if (quote
== '"' && p
[1] == '"')
253 cmd
= ++p
; // a quoted quote
257 cmd
= p
+ 1; // point to after end
263 /* Perform a glob on word if it contains wildcard characters.
264 Also quote every character between quotes to force glob to
265 treat the characters literally. */
267 globify (char *word
, char **&argv
, int &argc
, int &argvlen
)
269 if (*word
!= '~' && strpbrk (word
, "?*[\"\'(){}") == NULL
)
274 int dos_spec
= isdrive (word
);
275 if (!dos_spec
&& isquote (*word
) && word
[1] && word
[2])
276 dos_spec
= isdrive (word
+ 1);
278 /* We'll need more space if there are quoting characters in
279 word. If that is the case, doubling the size of the
280 string should provide more than enough space. */
281 if (strpbrk (word
, "'\""))
283 char pattern
[strlen (word
) + ((dos_spec
+ 1) * n
) + 1];
285 /* Fill pattern with characters from word, quoting any
286 characters found within quotes. */
287 for (p
= pattern
, s
= word
; *s
!= '\000'; s
++, p
++)
290 if (dos_spec
&& *s
== '\\')
297 while (*++s
&& *s
!= quote
)
299 if (dos_spec
|| *s
!= '\\')
301 else if (s
[1] == quote
|| s
[1] == '\\')
317 /* Attempt to match the argument. Return just word (minus quoting) if no match. */
318 if (glob (pattern
, GLOB_TILDE
| GLOB_NOCHECK
| GLOB_BRACE
| GLOB_QUOTE
, NULL
, &gl
) || !gl
.gl_pathc
)
321 /* Allocate enough space in argv for the matched filenames. */
323 if ((argc
+= gl
.gl_pathc
) > argvlen
)
326 argv
= (char **) realloc (argv
, (1 + argvlen
) * sizeof (argv
[0]));
329 /* Copy the matched filenames to argv. */
330 char **gv
= gl
.gl_pathv
;
331 char **av
= argv
+ n
;
334 debug_printf ("argv[%d] = '%s'", n
++, *gv
);
338 /* Clean up after glob. */
343 /* Build argv, argc from string passed from Windows. */
345 static void __stdcall
346 build_argv (char *cmd
, char **&argv
, int &argc
, int winshell
)
349 int nesting
= 0; // monitor "nesting" from insert_file
355 /* Scan command line until there is nothing left. */
365 /* Found the beginning of an argument. */
367 char *sawquote
= NULL
;
370 if (*cmd
!= '"' && (!winshell
|| *cmd
!= '\''))
371 cmd
++; // Skip over this character
373 /* Skip over characters until the closing quote */
376 cmd
= quoted (cmd
, winshell
&& argc
> 0);
378 if (issep (*cmd
)) // End of argument if space
382 *cmd
++ = '\0'; // Terminate `word'
384 /* Possibly look for @file construction assuming that this isn't
385 the very first argument and the @ wasn't quoted */
386 if (argc
&& sawquote
!= word
&& *word
== '@')
388 if (++nesting
> MAX_AT_FILE_LEVEL
)
389 api_fatal ("Too many levels of nesting for %s", word
);
390 if (insert_file (word
, cmd
))
391 continue; // There's new stuff in cmd now
394 /* See if we need to allocate more space for argv */
398 argv
= (char **) realloc (argv
, (1 + argvlen
) * sizeof (argv
[0]));
401 /* Add word to argv file after (optional) wildcard expansion. */
402 if (!winshell
|| !argc
|| !globify (word
, argv
, argc
, argvlen
))
404 debug_printf ("argv[%d] = '%s'", argc
, word
);
411 debug_printf ("argc %d", argc
);
414 /* sanity and sync check */
416 check_sanity_and_sync (per_process
*p
)
418 /* Sanity check to make sure developers didn't change the per_process */
419 /* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
420 /* about changing it]. */
421 if (sizeof (per_process
) != SIZEOF_PER_PROCESS
)
423 api_fatal ("per_process sanity check failed");
426 /* Make sure that the app and the dll are in sync. */
428 /* Complain if older than last incompatible change */
429 if (p
->dll_major
< CYGWIN_VERSION_DLL_EPOCH
)
430 api_fatal ("cygwin DLL and APP are out of sync -- DLL version mismatch %d < %d",
431 p
->dll_major
, CYGWIN_VERSION_DLL_EPOCH
);
433 /* magic_biscuit != 0 if using the old style version numbering scheme. */
434 if (p
->magic_biscuit
!= SIZEOF_PER_PROCESS
)
435 api_fatal ("Incompatible cygwin .dll -- incompatible per_process info %d != %d",
436 p
->magic_biscuit
, SIZEOF_PER_PROCESS
);
438 /* Complain if incompatible API changes made */
439 if (p
->api_major
!= cygwin_version
.api_major
)
440 api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d < %d",
441 p
->api_major
, cygwin_version
.api_major
);
443 if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p
->dll_major
, p
->dll_minor
) <=
444 CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK
)
445 signal_shift_subtract
= 0;
448 child_info NO_COPY
*child_proc_info
= NULL
;
449 static MEMORY_BASIC_INFORMATION NO_COPY sm
;
451 #define CYGWIN_GUARD ((wincap.has_page_guard ()) ? \
452 PAGE_EXECUTE_READWRITE|PAGE_GUARD : PAGE_NOACCESS)
456 alloc_stack_hard_way (child_info_fork
*ci
, volatile char *b
)
458 void *new_stack_pointer
;
459 MEMORY_BASIC_INFORMATION m
;
462 LPBYTE curbot
= (LPBYTE
) sm
.BaseAddress
+ sm
.RegionSize
;
465 if (ci
->stacktop
> (LPBYTE
) sm
.AllocationBase
&& ci
->stacktop
< curbot
)
468 newlen
= (LPBYTE
) ci
->stackbottom
- (LPBYTE
) curbot
;
473 newbase
= ci
->stacktop
;
474 newlen
= (DWORD
) ci
->stackbottom
- (DWORD
) ci
->stacktop
;
477 if (!VirtualAlloc (newbase
, newlen
, MEM_RESERVE
, PAGE_NOACCESS
))
478 api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
479 ci
->stacktop
, ci
->stackbottom
);
481 new_stack_pointer
= (void *) ((LPBYTE
) ci
->stackbottom
- ci
->stacksize
);
483 if (!VirtualAlloc (new_stack_pointer
, ci
->stacksize
, MEM_COMMIT
,
484 PAGE_EXECUTE_READWRITE
))
485 api_fatal ("fork: can't commit memory for stack %p(%d), %E",
486 new_stack_pointer
, ci
->stacksize
);
487 if (!VirtualQuery ((LPCVOID
) new_stack_pointer
, &m
, sizeof m
))
488 api_fatal ("fork: couldn't get new stack info, %E");
491 m
.BaseAddress
= (LPVOID
)((DWORD
)m
.BaseAddress
- 1);
492 if (!VirtualAlloc ((LPVOID
) m
.BaseAddress
, 1, MEM_COMMIT
,
494 api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
497 if (!VirtualQuery ((LPCVOID
) m
.BaseAddress
, &m
, sizeof m
))
498 api_fatal ("fork: couldn't get new stack info, %E");
499 ci
->stacktop
= m
.BaseAddress
;
503 /* extend the stack prior to fork longjmp */
506 alloc_stack (child_info_fork
*ci
)
508 /* FIXME: adding 16384 seems to avoid a stack copy problem during
509 fork on Win95, but I don't know exactly why yet. DJ */
510 volatile char b
[ci
->stacksize
+ 16384];
512 if (!VirtualQuery ((LPCVOID
) &b
, &sm
, sizeof sm
))
513 api_fatal ("fork: couldn't get stack info, %E");
515 if (sm
.AllocationBase
!= ci
->stacktop
)
516 alloc_stack_hard_way (ci
, b
+ sizeof (b
) - 1);
523 static NO_COPY
int mypid
= 0;
525 int _declspec(dllexport
) __argc
;
526 char _declspec(dllexport
) **__argv
;
527 vfork_save NO_COPY
*main_vfork
= NULL
;
530 sigthread::init (const char *s
)
532 InitializeCriticalSection (&lock
);
533 id
= GetCurrentThreadId ();
536 /* Take over from libc's crt0.o and start the application. Note the
537 various special cases when Cygwin DLL is being runtime loaded (as
538 opposed to being link-time loaded by Cygwin apps) from a non
539 cygwin app via LoadLibrary. */
543 /* According to onno@stack.urc.tue.nl, the exception handler record must
545 /* FIXME: Verify forked children get their exception handler set up ok. */
546 exception_list cygwin_except_entry
;
548 /* Initialize SIGSEGV handling, etc. */
549 init_exceptions (&cygwin_except_entry
);
551 /* Set the os_being_run global. */
553 check_sanity_and_sync (user_data
);
555 do_global_ctors (&__CTOR_LIST__
, 1);
557 /* Nasty static stuff needed by newlib -- point to a local copy of
559 Note: this MUST be done here (before the forkee code) as the
560 fork copy code doesn't copy the data in libccrt0.cc (that's why we
561 pass in the per_process struct into the .dll from libccrt0). */
563 _impure_ptr
= &reent_data
;
565 user_data
->resourcelocks
->Init ();
566 user_data
->threadinterface
->Init ();
568 mainthread
.init ("mainthread"); // For use in determining if signals
569 // should be blocked.
576 if (!child_proc_info
)
580 bool close_ppid_handle
= false;
581 bool close_hexec_proc
= false;
582 switch (child_proc_info
->type
)
585 alloc_stack (fork_info
);
586 cygheap_fixup_in_child (0);
589 close_ppid_handle
= !!child_proc_info
->pppid_handle
;
592 /* Have to delay closes until after cygheap is setup */
593 close_hexec_proc
= !!spawn_info
->hexec_proc
;
594 close_ppid_handle
= !!child_proc_info
->pppid_handle
;
597 hexec_proc
= spawn_info
->hexec_proc
;
600 cygheap_fixup_in_child (1);
602 if (!spawn_info
->moreinfo
->myself_pinfo
||
603 !DuplicateHandle (hMainProc
, spawn_info
->moreinfo
->myself_pinfo
,
605 DUPLICATE_SAME_ACCESS
| DUPLICATE_CLOSE_SOURCE
))
607 set_myself (mypid
, h
);
608 __argc
= spawn_info
->moreinfo
->argc
;
609 __argv
= spawn_info
->moreinfo
->argv
;
610 envp
= spawn_info
->moreinfo
->envp
;
611 envc
= spawn_info
->moreinfo
->envc
;
612 cygheap
->fdtab
.fixup_after_exec (spawn_info
->parent
);
613 signal_fixup_after_exec ();
614 CloseHandle (spawn_info
->parent
);
615 if (spawn_info
->moreinfo
->old_title
)
617 old_title
= strcpy (title_buf
, spawn_info
->moreinfo
->old_title
);
618 cfree (spawn_info
->moreinfo
->old_title
);
622 if (close_hexec_proc
)
623 CloseHandle (spawn_info
->hexec_proc
);
624 if (close_ppid_handle
)
625 CloseHandle (child_proc_info
->pppid_handle
);
628 ProtectHandle (hMainProc
);
629 ProtectHandle (hMainThread
);
632 /* Initialize pthread mainthread when not forked and it is save to call new,
633 otherwise it is reinitalized in fixup_after_fork */
634 if (!user_data
->forkee
)
635 pthread::init_mainthread ();
638 strace
.microseconds ();
641 /* Initialize debug muto, if DLL is built with --enable-debugging.
642 Need to do this before any helper threads start. */
645 cygheap
->fdtab
.vfork_child_fixup ();
647 (void) SetErrorMode (SEM_FAILCRITICALERRORS
);
649 /* Initialize events. */
652 cygheap
->cwd
.init ();
653 main_vfork
= vfork_storage
.create ();
655 cygbench ("pre-forkee");
656 if (user_data
->forkee
)
658 /* If we've played with the stack, stacksize != 0. That means that
659 fork() was invoked from other than the main thread. Make sure that
660 frame pointer is referencing the new stack so that the OS knows what
661 to do when it needs to increase the size of the stack.
663 NOTE: Don't do anything that involves the stack until you've completed
665 if (fork_info
->stacksize
)
667 asm ("movl %0,%%fs:4" : : "r" (fork_info
->stackbottom
));
668 asm ("movl %0,%%fs:8" : : "r" (fork_info
->stacktop
));
671 longjmp (fork_info
->jmp
, fork_info
->cygpid
);
676 extern void fork_init ();
681 /* Init global well known SID objects */
684 /* Initialize our process table entry. */
685 pinfo_init (envp
, envc
);
687 if (!old_title
&& GetConsoleTitle (title_buf
, TITLESIZE
))
688 old_title
= title_buf
;
690 /* Allocate cygheap->fdtab */
693 /* Initialize user info. */
696 /* Initialize signal/subprocess handling. */
699 /* Connect to tty. */
704 char *line
= GetCommandLineA ();
705 line
= strcpy ((char *) alloca (strlen (line
) + 1), line
);
707 if (current_codepage
== oem_cp
)
708 CharToOemA (line
, line
);
710 /* Scan the command line and build argv. Expand wildcards if not
711 called from another cygwin process. */
712 build_argv (line
, __argv
, __argc
,
713 NOTSTATE (myself
, PID_CYGPARENT
) && allow_glob
);
715 /* Convert argv[0] to posix rules if it's currently blatantly
717 if ((strchr (__argv
[0], ':')) || (strchr (__argv
[0], '\\')))
719 char *new_argv0
= (char *) alloca (MAX_PATH
);
720 cygwin_conv_to_posix_path (__argv
[0], new_argv0
);
721 __argv
[0] = new_argv0
;
725 __argc_safe
= __argc
;
726 if (user_data
->premain
[0])
727 for (unsigned int i
= 0; i
< PREMAIN_LEN
/ 2; i
++)
728 user_data
->premain
[i
] (__argc
, __argv
, user_data
);
730 /* Set up standard fds in file descriptor table. */
731 cygheap
->fdtab
.stdio_init ();
733 /* Set up __progname for getopt error call. */
734 if (__argv
[0] && (__progname
= strrchr (__argv
[0], '/')))
737 __progname
= __argv
[0];
740 char *cp
= strchr (__progname
, '\0') - 4;
741 if (cp
> __progname
&& strcasematch (cp
, ".exe"))
745 /* Set new console title if appropriate. */
747 if (display_title
&& !dynamically_loaded
)
749 char *cp
= __progname
;
750 if (strip_title_path
)
751 for (char *ptr
= cp
; *ptr
&& *ptr
!= ' '; ptr
++)
754 set_console_title (cp
);
757 cygwin_finished_initializing
= 1;
758 /* Call init of loaded dlls. */
761 /* Execute any specified "premain" functions */
762 if (user_data
->premain
[PREMAIN_LEN
/ 2])
763 for (unsigned int i
= PREMAIN_LEN
/ 2; i
< PREMAIN_LEN
; i
++)
764 user_data
->premain
[i
] (__argc
, __argv
, user_data
);
766 debug_printf ("user_data->main %p", user_data
->main
);
768 if (dynamically_loaded
)
774 /* Disable case-insensitive globbing */
775 ignore_case_with_glob
= FALSE
;
777 /* Flush signals and ensure that signal thread is up and running. Can't
778 do this for noncygwin case since the signal thread is blocked due to
779 LoadLibrary serialization. */
780 wait_for_sigthread ();
785 cygbench (__progname
);
787 exit (user_data
->main (__argc
, __argv
, *user_data
->envptr
));
794 debug_printf ("break here");
802 char buf
[MAX_PATH
+ 1];
804 if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf
, sizeof (buf
) - 1))
806 DWORD ms
= atoi (buf
);
808 len
= GetModuleFileName (NULL
, buf
, MAX_PATH
);
809 console_printf ("Sleeping %d, pid %u %s\n", ms
, GetCurrentProcessId (), buf
);
812 if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf
, sizeof (buf
) - 1))
814 char buf1
[MAX_PATH
+ 1];
815 len
= GetModuleFileName (NULL
, buf1
, MAX_PATH
);
818 char *p
= strchr (buf
, ':');
820 p
= (char *) "gdb.exe -nw";
823 if (strstr (buf1
, buf
))
825 error_start_init (p
);
832 if (GetEnvironmentVariable ("CYGWIN_TESTING", buf
, sizeof (buf
) - 1))
835 if ((len
= GetModuleFileName (cygwin_hmodule
, buf
, MAX_PATH
))
836 && len
> sizeof ("new-cygwin1.dll")
837 && strcasematch (buf
+ len
- sizeof ("new-cygwin1.dll"),
838 "\\new-cygwin1.dll"))
839 _cygwin_testing_magic
= 0x10;
843 /* Wrap the real one, otherwise gdb gets confused about
844 two symbols with the same name, but different addresses.
846 UPTR is a pointer to global data that lives on the libc side of the
847 line [if one distinguishes the application from the dll]. */
849 extern "C" void __stdcall
854 char zeros
[sizeof (fork_info
->zero
)] = {0};
855 static NO_COPY STARTUPINFO si
;
857 main_environ
= user_data
->envptr
;
858 *main_environ
= NULL
;
860 init_console_handler ();
861 init_global_security ();
862 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
863 GetCurrentProcess (), &hMainProc
, 0, FALSE
,
864 DUPLICATE_SAME_ACCESS
))
865 hMainProc
= GetCurrentProcess ();
867 DuplicateHandle (hMainProc
, GetCurrentThread (), hMainProc
,
868 &hMainThread
, 0, false, DUPLICATE_SAME_ACCESS
);
870 GetStartupInfo (&si
);
871 child_proc_info
= (child_info
*) si
.lpReserved2
;
872 if (si
.cbReserved2
< EXEC_MAGIC_SIZE
|| !child_proc_info
873 || memcmp (child_proc_info
->zero
, zeros
, sizeof (zeros
)) != 0)
874 child_proc_info
= NULL
;
877 if ((child_proc_info
->intro
& OPROC_MAGIC_MASK
) == OPROC_MAGIC_GENERIC
)
878 multiple_cygwin_problem ("proc", child_proc_info
->intro
, 0);
879 else if (child_proc_info
->intro
== PROC_MAGIC_GENERIC
880 && child_proc_info
->magic
!= CHILD_INFO_MAGIC
)
881 multiple_cygwin_problem ("proc", child_proc_info
->magic
,
883 else if (child_proc_info
->cygheap
!= (void *) &_cygheap_start
)
884 multiple_cygwin_problem ("cygheap", (DWORD
) child_proc_info
->cygheap
,
885 (DWORD
) &_cygheap_start
);
886 unsigned should_be_cb
= 0;
887 switch (child_proc_info
->type
)
890 user_data
->forkee
= child_proc_info
->cygpid
;
891 should_be_cb
= sizeof (child_info_fork
);
896 should_be_cb
= sizeof (child_info
);
897 if (should_be_cb
!= child_proc_info
->cb
)
898 multiple_cygwin_problem ("proc size", child_proc_info
->cb
, should_be_cb
);
899 else if (sizeof (fhandler_union
) != child_proc_info
->fhandler_union_cb
)
900 multiple_cygwin_problem ("fhandler size", child_proc_info
->fhandler_union_cb
, sizeof (fhandler_union
));
903 cygwin_mount_h
= child_proc_info
->mount_h
;
904 mypid
= child_proc_info
->cygpid
;
908 system_printf ("unknown exec type %d", child_proc_info
->type
);
909 /* intentionally fall through */
911 child_proc_info
= NULL
;
919 dll_crt0 (per_process
*uptr
)
922 /* Set the local copy of the pointer into the user space. */
923 if (uptr
&& uptr
!= user_data
)
925 memcpy (user_data
, uptr
, per_process_overwrite
);
926 *(user_data
->impure_ptr_ptr
) = &reent_data
;
931 /* This must be called by anyone who uses LoadLibrary to load cygwin1.dll */
938 if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
939 GetCurrentProcess (), &hMainProc
, 0, FALSE
,
940 DUPLICATE_SAME_ACCESS
))
941 hMainProc
= GetCurrentProcess ();
943 DuplicateHandle (hMainProc
, GetCurrentThread (), hMainProc
,
944 &hMainThread
, 0, FALSE
, DUPLICATE_SAME_ACCESS
);
945 user_data
->magic_biscuit
= sizeof (per_process
);
947 user_data
->envptr
= &envp
;
948 user_data
->fmode_ptr
= &_fmode
;
956 do_global_ctors (user_data
->ctors
, FALSE
);
973 exit_states NO_COPY exit_state
;
974 extern CRITICAL_SECTION exit_lock
;
976 extern "C" void __stdcall
979 EnterCriticalSection (&exit_lock
);
980 UINT n
= (UINT
) status
;
982 syscall_printf ("do_exit (%d)", n
);
984 vfork_save
*vf
= vfork_storage
.val ();
985 if (vf
!= NULL
&& vf
->pid
< 0)
986 vf
->restore_exit (status
);
988 if (exit_state
< ES_THREADTERM
)
990 exit_state
= ES_THREADTERM
;
991 cygthread::terminate ();
994 if (exit_state
< ES_SIGNAL
)
996 exit_state
= ES_SIGNAL
;
997 if (!(n
& EXIT_REPARENTING
))
999 signal (SIGCHLD
, SIG_IGN
);
1000 signal (SIGHUP
, SIG_IGN
);
1001 signal (SIGINT
, SIG_IGN
);
1002 signal (SIGQUIT
, SIG_IGN
);
1006 if (exit_state
< ES_CLOSEALL
)
1008 exit_state
= ES_CLOSEALL
;
1012 if (exit_state
< ES_SIGPROCTERMINATE
)
1014 exit_state
= ES_SIGPROCTERMINATE
;
1015 sigproc_terminate ();
1018 myself
->stopsig
= 0;
1019 if (exit_state
< ES_TITLE
)
1021 exit_state
= ES_TITLE
;
1022 /* restore console title */
1023 if (old_title
&& display_title
)
1024 set_console_title (old_title
);
1027 if (exit_state
< ES_HUP_PGRP
)
1029 exit_state
= ES_HUP_PGRP
;
1030 /* Kill orphaned children on group leader exit */
1031 if (myself
->has_pgid_children
&& myself
->pid
== myself
->pgid
)
1033 sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
1034 myself
->pid
, myself
->pgid
);
1035 kill_pgrp (myself
->pgid
, -SIGHUP
);
1039 if (exit_state
< ES_HUP_SID
)
1041 exit_state
= ES_HUP_SID
;
1042 /* Kill the foreground process group on session leader exit */
1043 if (getpgrp () > 0 && myself
->pid
== myself
->sid
&& real_tty_attached (myself
))
1045 tty
*tp
= cygwin_shared
->tty
[myself
->ctty
];
1046 sigproc_printf ("%d == sid %d, send SIGHUP to children",
1047 myself
->pid
, myself
->sid
);
1049 /* CGF FIXME: This can't be right. */
1050 if (tp
->getsid () == myself
->sid
)
1051 tp
->kill_pgrp (SIGHUP
);
1056 if (exit_state
< ES_TTY_TERMINATE
)
1058 exit_state
= ES_TTY_TERMINATE
;
1062 if (exit_state
< ES_EVENTS_TERMINATE
)
1064 exit_state
= ES_EVENTS_TERMINATE
;
1065 events_terminate ();
1068 minimal_printf ("winpid %d, exit %d", GetCurrentProcessId (), n
);
1072 static muto
*atexit_lock
;
1075 cygwin_atexit (void (*function
)(void))
1079 new_muto (atexit_lock
);
1080 atexit_lock
->acquire ();
1081 res
= atexit (function
);
1082 atexit_lock
->release ();
1090 atexit_lock
->acquire ();
1097 do_exit ((DWORD
) n
& 0xffff);
1101 __api_fatal (const char *fmt
, ...)
1107 __small_vsprintf (buf
, fmt
, ap
);
1110 int len
= strlen (buf
);
1112 (void) WriteFile (GetStdHandle (STD_ERROR_HANDLE
), buf
, len
, &done
, 0);
1114 /* Make sure that the message shows up on the screen, too, since this is
1116 if (GetFileType (GetStdHandle (STD_ERROR_HANDLE
)) != FILE_TYPE_CHAR
)
1118 HANDLE h
= CreateFile ("CONOUT$", GENERIC_READ
| GENERIC_WRITE
,
1119 FILE_SHARE_WRITE
| FILE_SHARE_WRITE
,
1120 &sec_none
, OPEN_EXISTING
, 0, 0);
1121 if (h
!= INVALID_HANDLE_VALUE
)
1122 (void) WriteFile (h
, buf
, len
, &done
, 0);
1125 /* We are going down without mercy. Make sure we reset
1126 our process_state. */
1127 sigproc_terminate ();
1129 (void) try_to_debug ();
1135 multiple_cygwin_problem (const char *what
, unsigned magic_version
, unsigned version
)
1137 if (_cygwin_testing
&& (strstr (what
, "proc") || strstr (what
, "cygheap")))
1139 child_proc_info
->type
= _PROC_WHOOPS
;
1144 if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf
, sizeof (buf
)))
1147 if (CYGWIN_VERSION_MAGIC_VERSION (magic_version
) == version
)
1148 system_printf ("%s magic number mismatch detected - %p/%p", what
, magic_version
, version
);
1150 api_fatal ("%s version mismatch detected - %p/%p.\n\
1151 You have multiple copies of cygwin1.dll on your system.\n\
1152 Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
1153 and delete all but the most recent version. The most recent version *should*\n\
1154 reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
1155 installed the cygwin distribution.", what
, magic_version
, version
);
1160 cygbench (const char *s
)
1163 if (GetEnvironmentVariable ("CYGWIN_BENCH", buf
, sizeof (buf
)))
1164 small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s
, strace
.microseconds ());