Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/dcrt0.cc')
-rw-r--r--winsup/cygwin/dcrt0.cc311
1 files changed, 194 insertions, 117 deletions
diff --git a/winsup/cygwin/dcrt0.cc b/winsup/cygwin/dcrt0.cc
index 9fb6ca906..701fb140c 100644
--- a/winsup/cygwin/dcrt0.cc
+++ b/winsup/cygwin/dcrt0.cc
@@ -1,6 +1,6 @@
/* dcrt0.cc -- essentially the main() for the Cygwin dll
- Copyright 1996, 1997, 1998, 1999, 2000, 2001 Red Hat, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002 Red Hat, Inc.
This file is part of Cygwin.
@@ -17,10 +17,9 @@ details. */
#include <limits.h>
#include <wingdi.h>
#include <winuser.h>
-#include "sync.h"
+#include <errno.h>
#include "sigproc.h"
#include "pinfo.h"
-#include "heap.h"
#include "cygerrno.h"
#define NEED_VFORK
#include "perprocess.h"
@@ -29,20 +28,19 @@ details. */
#include "path.h"
#include "dtable.h"
#include "cygheap.h"
-#include "child_info.h"
+#include "child_info_magic.h"
#include "perthread.h"
#include "shared_info.h"
#include "cygwin_version.h"
#include "dll_init.h"
-#include "cygwin/cygserver_transport.h"
-#include "cygwin/cygserver.h"
+#include "cygthread.h"
#define MAX_AT_FILE_LEVEL 10
#define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
-HANDLE NO_COPY hMainProc = NULL;
-HANDLE NO_COPY hMainThread = NULL;
+HANDLE NO_COPY hMainProc;
+HANDLE NO_COPY hMainThread;
sigthread NO_COPY mainthread; // ID of the main thread
@@ -74,14 +72,12 @@ ResourceLocks _reslock NO_COPY;
MTinterface _mtinterf;
bool NO_COPY _cygwin_testing;
+unsigned NO_COPY _cygwin_testing_magic;
+
+char NO_COPY almost_null[1];
extern "C"
{
- void *export_malloc (unsigned int);
- void export_free (void *);
- void *export_realloc (void *, unsigned int);
- void *export_calloc (unsigned int, unsigned int);
-
/* This is an exported copy of environ which can be used by DLLs
which use cygwin.dll. */
char **__cygwin_environ;
@@ -94,12 +90,12 @@ extern "C"
/* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
/* dll_major */ CYGWIN_VERSION_DLL_MINOR,
/* impure_ptr_ptr */ NULL, /* envptr */ NULL,
- /* malloc */ export_malloc, /* free */ export_free,
- /* realloc */ export_realloc,
+ /* malloc */ malloc, /* free */ free,
+ /* realloc */ realloc,
/* fmode_ptr */ NULL, /* main */ NULL, /* ctors */ NULL,
/* dtors */ NULL, /* data_start */ NULL, /* data_end */ NULL,
/* bss_start */ NULL, /* bss_end */ NULL,
- /* calloc */ export_calloc,
+ /* calloc */ calloc,
/* premain */ {NULL, NULL, NULL, NULL},
/* run_ctors_p */ 0,
/* unused */ {0, 0, 0, 0, 0, 0, 0},
@@ -157,10 +153,10 @@ do_global_ctors (void (**in_pfunc)(), int force)
}
/*
- * Replaces -@file in the command line with the contents of the file.
- * There may be multiple -@file's in a single command line
- * A \-@file is replaced with -@file so that echo \-@foo would print
- * -@foo and not the contents of foo.
+ * Replaces @file in the command line with the contents of the file.
+ * There may be multiple @file's in a single command line
+ * A \@file is replaced with @file so that echo \@foo would print
+ * @foo and not the contents of foo.
*/
static int __stdcall
insert_file (char *name, char *&cmd)
@@ -451,13 +447,11 @@ check_sanity_and_sync (per_process *p)
signal_shift_subtract = 0;
}
-static NO_COPY STARTUPINFO si;
-# define fork_info ((struct child_info_fork *)(si.lpReserved2))
-# define spawn_info ((struct child_info_spawn *)(si.lpReserved2))
-child_info_fork NO_COPY *child_proc_info = NULL;
-static MEMORY_BASIC_INFORMATION sm;
+child_info NO_COPY *child_proc_info = NULL;
+static MEMORY_BASIC_INFORMATION NO_COPY sm;
-#define CYGWIN_GUARD ((wincap.has_page_guard ()) ? PAGE_GUARD : PAGE_NOACCESS)
+#define CYGWIN_GUARD ((wincap.has_page_guard ()) ? \
+ PAGE_EXECUTE_READWRITE|PAGE_GUARD : PAGE_NOACCESS)
// __inline__ void
extern void
@@ -498,7 +492,7 @@ alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
{
m.BaseAddress = (LPVOID)((DWORD)m.BaseAddress - 1);
if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
- PAGE_EXECUTE_READWRITE|CYGWIN_GUARD))
+ CYGWIN_GUARD))
api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
m.BaseAddress);
}
@@ -517,18 +511,13 @@ alloc_stack (child_info_fork *ci)
fork on Win95, but I don't know exactly why yet. DJ */
volatile char b[ci->stacksize + 16384];
- if (ci->type == PROC_FORK)
- ci->stacksize = 0; // flag to fork not to do any funny business
- else
- {
- if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
- api_fatal ("fork: couldn't get stack info, %E");
+ if (!VirtualQuery ((LPCVOID) &b, &sm, sizeof sm))
+ api_fatal ("fork: couldn't get stack info, %E");
- if (sm.AllocationBase != ci->stacktop)
- alloc_stack_hard_way (ci, b + sizeof (b) - 1);
- else
- ci->stacksize = 0;
- }
+ if (sm.AllocationBase != ci->stacktop)
+ alloc_stack_hard_way (ci, b + sizeof (b) - 1);
+ else
+ ci->stacksize = 0;
return;
}
@@ -560,12 +549,12 @@ dll_crt0_1 ()
/* Initialize SIGSEGV handling, etc. */
init_exceptions (&cygwin_except_entry);
- do_global_ctors (&__CTOR_LIST__, 1);
-
/* Set the os_being_run global. */
wincap.init ();
check_sanity_and_sync (user_data);
+ do_global_ctors (&__CTOR_LIST__, 1);
+
/* Nasty static stuff needed by newlib -- point to a local copy of
the reent stuff.
Note: this MUST be done here (before the forkee code) as the
@@ -577,11 +566,6 @@ dll_crt0_1 ()
user_data->resourcelocks->Init ();
user_data->threadinterface->Init (user_data->forkee);
- threadname_init ();
- debug_init ();
- (void) getpagesize (); /* initialize page size constant */
-
- regthread ("main", GetCurrentThreadId ());
mainthread.init ("mainthread"); // For use in determining if signals
// should be blocked.
@@ -590,30 +574,32 @@ dll_crt0_1 ()
if (child_proc_info)
{
+ bool close_ppid_handle = false;
+ bool close_hexec_proc = false;
switch (child_proc_info->type)
{
- case PROC_FORK:
- case PROC_FORK1:
- cygheap_fixup_in_child (child_proc_info, 0);
+ case _PROC_FORK:
+ cygheap_fixup_in_child (0);
alloc_stack (fork_info);
set_myself (mypid);
- ProtectHandle (child_proc_info->forker_finished);
+ close_ppid_handle = !!child_proc_info->pppid_handle;
break;
- case PROC_SPAWN:
- CloseHandle (spawn_info->hexec_proc);
+ case _PROC_SPAWN:
+ /* Have to delay closes until after cygheap is setup */
+ close_hexec_proc = !!spawn_info->hexec_proc;
+ close_ppid_handle = !!child_proc_info->pppid_handle;
goto around;
- case PROC_EXEC:
+ case _PROC_EXEC:
hexec_proc = spawn_info->hexec_proc;
around:
HANDLE h;
- cygheap_fixup_in_child (spawn_info, 1);
+ cygheap_fixup_in_child (1);
if (!spawn_info->moreinfo->myself_pinfo ||
!DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
hMainProc, &h, 0, 0,
DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
h = NULL;
set_myself (mypid, h);
- myself->uid = spawn_info->moreinfo->uid;
__argc = spawn_info->moreinfo->argc;
__argv = spawn_info->moreinfo->argv;
envp = spawn_info->moreinfo->envp;
@@ -626,19 +612,26 @@ dll_crt0_1 ()
old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
cfree (spawn_info->moreinfo->old_title);
}
- if (child_proc_info->subproc_ready)
- ProtectHandle (child_proc_info->subproc_ready);
- if (myself->uid == USHRT_MAX)
- cygheap->user.set_sid (NULL);
break;
}
+ if (close_hexec_proc)
+ CloseHandle (spawn_info->hexec_proc);
+ if (close_ppid_handle)
+ CloseHandle (child_proc_info->pppid_handle);
}
- ProtectHandle (hMainProc);
- ProtectHandle (hMainThread);
/* Initialize the cygwin subsystem if this is the first process,
or attach to shared data structures if it's already running. */
memory_init ();
+ cygthread::init ();
+
+ ProtectHandle (hMainProc);
+ ProtectHandle (hMainThread);
+
+ /* Initialize debug muto, if DLL is built with --enable-debugging.
+ Need to do this before any helper threads start. */
+ debug_init ();
+
cygheap->fdtab.vfork_child_fixup ();
(void) SetErrorMode (SEM_FAILCRITICALERRORS);
@@ -684,14 +677,13 @@ dll_crt0_1 ()
/* Allocate cygheap->fdtab */
dtable_init ();
-/* Initialize uid, gid. */
- uinfo_init ();
+ /* Initialize uid, gid if necessary. */
+ if (child_proc_info == NULL || spawn_info->moreinfo->uid == ILLEGAL_UID)
+ uinfo_init ();
/* Initialize signal/subprocess handling. */
sigproc_init ();
- cygserver_init ();
-
/* Connect to tty. */
tty_init ();
@@ -714,9 +706,6 @@ dll_crt0_1 ()
{
char *new_argv0 = (char *) alloca (MAX_PATH);
cygwin_conv_to_posix_path (__argv[0], new_argv0);
- char *p = strchr (new_argv0, '\0') - 4;
- if (p > new_argv0 && strcasematch (p, ".exe"))
- *p = '\0';
__argv[0] = new_argv0;
}
}
@@ -726,10 +715,19 @@ dll_crt0_1 ()
user_data->premain[i] (__argc, __argv, user_data);
/* Set up standard fds in file descriptor table. */
- stdio_init ();
+ cygheap->fdtab.stdio_init ();
/* Set up __progname for getopt error call. */
- __progname = __argv[0];
+ if (__argv[0] && (__progname = strrchr (__argv[0], '/')))
+ ++__progname;
+ else
+ __progname = __argv[0];
+ if (__progname)
+ {
+ char *cp = strchr (__progname, '\0') - 4;
+ if (cp > __progname && strcasematch (cp, ".exe"))
+ *cp = '\0';
+ }
/* Set new console title if appropriate. */
@@ -766,7 +764,7 @@ dll_crt0_1 ()
/* Flush signals and ensure that signal thread is up and running. Can't
do this for noncygwin case since the signal thread is blocked due to
LoadLibrary serialization. */
- sig_send (NULL, __SIGFLUSH);
+ wait_for_sigthread ();
set_errno (0);
@@ -776,6 +774,59 @@ dll_crt0_1 ()
exit (user_data->main (__argc, __argv, *user_data->envptr));
}
+#ifdef DEBUGGING
+void
+break_here ()
+{
+ debug_printf ("break here");
+}
+#endif
+
+void
+initial_env ()
+{
+ DWORD len;
+ char buf[MAX_PATH + 1];
+#ifdef DEBUGGING
+ if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
+ {
+ DWORD ms = atoi (buf);
+ buf[0] = '\0';
+ len = GetModuleFileName (NULL, buf, MAX_PATH);
+ console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
+ Sleep (ms);
+ }
+ if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
+ {
+ char buf1[MAX_PATH + 1];
+ len = GetModuleFileName (NULL, buf1, MAX_PATH);
+ strlwr (buf1);
+ strlwr (buf);
+ char *p = strchr (buf, '=');
+ if (!p)
+ p = (char *) "gdb.exe -nw";
+ else
+ *p++ = '\0';
+ if (strstr (buf1, buf))
+ {
+ error_start_init (p);
+ try_to_debug ();
+ break_here ();
+ }
+ }
+#endif
+
+ if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
+ {
+ _cygwin_testing = 1;
+ if ((len = GetModuleFileName (cygwin_hmodule, buf, MAX_PATH))
+ && len > sizeof ("new-cygwin1.dll")
+ && strcasematch (buf + len - sizeof ("new-cygwin1.dll"),
+ "\\new-cygwin1.dll"))
+ _cygwin_testing_magic = 0x10;
+ }
+}
+
/* Wrap the real one, otherwise gdb gets confused about
two symbols with the same name, but different addresses.
@@ -785,19 +836,10 @@ dll_crt0_1 ()
extern "C" void __stdcall
_dll_crt0 ()
{
- char envbuf[8];
-#ifdef DEBUGGING
- if (GetEnvironmentVariable ("CYGWIN_SLEEP", envbuf, sizeof (envbuf) - 1))
- {
- console_printf ("Sleeping %d, pid %u\n", atoi (envbuf), GetCurrentProcessId ());
- Sleep (atoi (envbuf));
- }
-#endif
-
- if (GetEnvironmentVariable ("CYGWIN_TESTING", envbuf, sizeof (envbuf) - 1))
- _cygwin_testing = 1;
-
+ DECLARE_TLS_STORAGE;
+ initial_env ();
char zeros[sizeof (fork_info->zero)] = {0};
+ static NO_COPY STARTUPINFO si;
#ifdef DEBUGGING
strace.microseconds ();
#endif
@@ -805,7 +847,7 @@ _dll_crt0 ()
main_environ = user_data->envptr;
*main_environ = NULL;
- set_console_handler ();
+ early_stuff_init ();
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
GetCurrentProcess (), &hMainProc, 0, FALSE,
DUPLICATE_SAME_ACCESS))
@@ -815,34 +857,47 @@ _dll_crt0 ()
&hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
GetStartupInfo (&si);
- if (si.cbReserved2 >= EXEC_MAGIC_SIZE &&
- memcmp (fork_info->zero, zeros, sizeof (zeros)) == 0)
+ child_proc_info = (child_info *) si.lpReserved2;
+ if (si.cbReserved2 < EXEC_MAGIC_SIZE || !child_proc_info
+ || memcmp (child_proc_info->zero, zeros, sizeof (zeros)) != 0)
+ child_proc_info = NULL;
+ else
{
- switch (fork_info->type)
+ if ((child_proc_info->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
+ multiple_cygwin_problem ("proc", child_proc_info->intro, 0);
+ else if (child_proc_info->intro == PROC_MAGIC_GENERIC
+ && child_proc_info->magic != CHILD_INFO_MAGIC)
+ multiple_cygwin_problem ("proc", child_proc_info->magic,
+ CHILD_INFO_MAGIC);
+ else if (child_proc_info->cygheap != (void *) &_cygheap_start)
+ multiple_cygwin_problem ("cygheap", (DWORD) child_proc_info->cygheap,
+ (DWORD) &_cygheap_start);
+ unsigned should_be_cb = 0;
+ switch (child_proc_info->type)
{
- case PROC_FORK:
- case PROC_FORK1:
- user_data->forkee = fork_info->cygpid;
- case PROC_SPAWN:
- if (fork_info->pppid_handle)
- CloseHandle (fork_info->pppid_handle);
- case PROC_EXEC:
- {
- child_proc_info = fork_info;
- cygwin_mount_h = child_proc_info->mount_h;
- mypid = child_proc_info->cygpid;
- break;
- }
+ case _PROC_FORK:
+ user_data->forkee = child_proc_info->cygpid;
+ should_be_cb = sizeof (child_info_fork);
+ /* fall through */;
+ case _PROC_SPAWN:
+ case _PROC_EXEC:
+ if (!should_be_cb)
+ should_be_cb = sizeof (child_info);
+ if (should_be_cb != child_proc_info->cb)
+ multiple_cygwin_problem ("proc size", child_proc_info->cb, should_be_cb);
+ else if (sizeof (fhandler_union) != child_proc_info->fhandler_union_cb)
+ multiple_cygwin_problem ("fhandler size", child_proc_info->fhandler_union_cb, sizeof (fhandler_union));
+ else
+ {
+ cygwin_mount_h = child_proc_info->mount_h;
+ mypid = child_proc_info->cygpid;
+ break;
+ }
default:
- if (_cygwin_testing)
- fork_info = NULL;
- else if ((fork_info->type & PROC_MAGIC_MASK) == PROC_MAGIC_GENERIC)
- api_fatal ("\
-You have multiple copies of cygwin1.dll on your system.\n\
-Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
-and delete all but the most recent version. This will probably be\n\
-the one that resides in x:\\cygwin\\bin, where 'x' is the drive on which\n\
-you have installed the cygwin distribution.\n");
+ system_printf ("unknown exec type %d", child_proc_info->type);
+ /* intentionally fall through */
+ case _PROC_WHOOPS:
+ child_proc_info = NULL;
break;
}
}
@@ -852,6 +907,7 @@ you have installed the cygwin distribution.\n");
void
dll_crt0 (per_process *uptr)
{
+ DECLARE_TLS_STORAGE;
/* Set the local copy of the pointer into the user space. */
if (uptr && uptr != user_data)
{
@@ -906,10 +962,7 @@ do_exit (int status)
vfork_save *vf = vfork_storage.val ();
if (vf != NULL && vf->pid < 0)
- {
- vf->pid = status < 0 ? status : -status;
- longjmp (vf->j, 1);
- }
+ vf->restore_exit (status);
if (exit_state < ES_SIGNAL)
{
@@ -962,7 +1015,7 @@ do_exit (int status)
/* CGF FIXME: This can't be right. */
if (tp->getsid () == myself->sid)
- kill_pgrp (tp->getpgid (), SIGHUP);
+ tp->kill_pgrp (SIGHUP);
}
tty_terminate ();
@@ -1000,10 +1053,10 @@ __api_fatal (const char *fmt, ...)
a serious error. */
if (GetFileType (GetStdHandle (STD_ERROR_HANDLE)) != FILE_TYPE_CHAR)
{
- HANDLE h = CreateFileA ("CONOUT$", GENERIC_READ|GENERIC_WRITE,
- FILE_SHARE_WRITE | FILE_SHARE_WRITE, &sec_none,
- OPEN_EXISTING, 0, 0);
- if (h)
+ HANDLE h = CreateFile ("CONOUT$", GENERIC_READ | GENERIC_WRITE,
+ FILE_SHARE_WRITE | FILE_SHARE_WRITE,
+ &sec_none, OPEN_EXISTING, 0, 0);
+ if (h != INVALID_HANDLE_VALUE)
(void) WriteFile (h, buf, len, &done, 0);
}
@@ -1016,6 +1069,30 @@ __api_fatal (const char *fmt, ...)
myself->exit (1);
}
+void
+multiple_cygwin_problem (const char *what, unsigned magic_version, unsigned version)
+{
+ if (_cygwin_testing && (strstr (what, "proc") || strstr (what, "cygheap")))
+ {
+ child_proc_info->type = _PROC_WHOOPS;
+ return;
+ }
+
+ char buf[1024];
+ if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf, sizeof (buf)))
+ return;
+
+ if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
+ system_printf ("%s magic number mismatch detected - %p/%p", what, magic_version, version);
+ else
+ api_fatal ("%s version mismatch detected - %p/%p.\n\
+You have multiple copies of cygwin1.dll on your system.\n\
+Search for cygwin1.dll using the Windows Start->Find/Search facility\n\
+and delete all but the most recent version. The most recent version *should*\n\
+reside in x:\\cygwin\\bin, where 'x' is the drive on which you have\n\
+installed the cygwin distribution.", what, magic_version, version);
+}
+
#ifdef DEBUGGING
void __stdcall
cygbench (const char *s)