/* dcrt0.cc -- essentially the main() for the Cygwin dll
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2007, 2008, 2009
Red Hat, Inc.
This file is part of Cygwin.
details. */
#include "winsup.h"
+#include "miscfuncs.h"
#include <unistd.h>
-#include <stdio.h>
#include <stdlib.h>
#include "glob.h"
-#include "exceptions.h"
#include <ctype.h>
-#include <limits.h>
-#include <wingdi.h>
-#include <winuser.h>
+#include <locale.h>
+#include "environ.h"
#include "sigproc.h"
#include "pinfo.h"
#include "cygerrno.h"
#define NEED_VFORK
#include "perprocess.h"
-#include "security.h"
#include "path.h"
#include "fhandler.h"
#include "dtable.h"
#include "shared_info.h"
#include "cygwin_version.h"
#include "dll_init.h"
-#include "sync.h"
#include "heap.h"
+#include "tls_pbuf.h"
#define MAX_AT_FILE_LEVEL 10
#define PREMAIN_LEN (sizeof (user_data->premain) / sizeof (user_data->premain[0]))
-extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
-
-HANDLE NO_COPY hMainProc = (HANDLE) -1;
-HANDLE NO_COPY hMainThread;
-HANDLE NO_COPY hProcToken;
-HANDLE NO_COPY hProcImpToken;
-
-muto NO_COPY lock_process::locker;
-
-bool display_title;
-bool strip_title_path;
-bool allow_glob = true;
-bool NO_COPY in_forkee;
-codepage_type current_codepage = ansi_cp;
-
-int __argc_safe;
-int _declspec(dllexport) __argc;
-char _declspec(dllexport) **__argv;
-#ifdef NEWVFORK
-vfork_save NO_COPY *main_vfork;
-#endif
-
-static int NO_COPY envc;
-char NO_COPY **envp;
+extern "C" void cygwin_exit (int) __attribute__ ((noreturn));
extern "C" void __sinit (_reent *);
-_cygtls NO_COPY *_main_tls;
-
-bool NO_COPY cygwin_finished_initializing;
-
-/* Used in SIGTOMASK for generating a bit for insertion into a sigset_t.
- This is subtracted from the signal number prior to shifting the bit.
- In older versions of cygwin, the signal was used as-is to shift the
- bit for masking. So, we'll temporarily detect this and set it to zero
- for programs that are linked using older cygwins. This is just a stopgap
- measure to allow an orderly transfer to the new, correct sigmask method. */
-unsigned NO_COPY int signal_shift_subtract = 1;
-
-ResourceLocks _reslock NO_COPY;
-MTinterface _mtinterf;
-
-bool NO_COPY _cygwin_testing;
-
-char NO_COPY almost_null[1];
+static int NO_COPY envc;
+static char NO_COPY **envp;
-extern "C"
-{
- /* This is an exported copy of environ which can be used by DLLs
- which use cygwin.dll. */
- char **__cygwin_environ;
- char ***main_environ;
- /* __progname used in getopt error message */
- char *__progname;
- struct per_process __cygwin_user_data =
- {/* initial_sp */ 0, /* magic_biscuit */ 0,
- /* dll_major */ CYGWIN_VERSION_DLL_MAJOR,
- /* dll_major */ CYGWIN_VERSION_DLL_MINOR,
- /* impure_ptr_ptr */ NULL, /* envptr */ NULL,
- /* 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 */ calloc,
- /* premain */ {NULL, NULL, NULL, NULL},
- /* run_ctors_p */ 0,
- /* unused */ {0, 0, 0, 0, 0, 0, 0},
- /* UNUSED forkee */ 0,
- /* hmodule */ NULL,
- /* api_major */ CYGWIN_VERSION_API_MAJOR,
- /* api_minor */ CYGWIN_VERSION_API_MINOR,
- /* unused2 */ {0, 0, 0, 0, 0},
- /* resourcelocks */ &_reslock, /* threadinterface */ &_mtinterf,
- /* impure_ptr */ _GLOBAL_REENT,
- };
- bool ignore_case_with_glob;
- int __declspec (dllexport) _check_for_executable = true;
-#ifdef DEBUGGING
- int pinger;
-#endif
-};
+static char title_buf[TITLESIZE + 1];
-char *old_title;
-char title_buf[TITLESIZE + 1];
+bool NO_COPY jit_debug;
static void
do_global_dtors ()
{
HANDLE f;
DWORD size;
-
- f = CreateFile (name + 1,
- GENERIC_READ, /* open for reading */
- FILE_SHARE_READ, /* share for reading */
- &sec_none_nih, /* no security */
- OPEN_EXISTING, /* existing file only */
- FILE_ATTRIBUTE_NORMAL, /* normal file */
- NULL); /* no attr. template */
+ tmp_pathbuf tp;
+
+ PWCHAR wname = tp.w_get ();
+ sys_mbstowcs (wname, NT_MAX_PATH, name + 1);
+ f = CreateFileW (wname,
+ GENERIC_READ, /* open for reading */
+ FILE_SHARE_READ, /* share for reading */
+ &sec_none_nih, /* default security */
+ OPEN_EXISTING, /* existing file only */
+ FILE_ATTRIBUTE_NORMAL,/* normal file */
+ NULL); /* no attr. template */
if (f == INVALID_HANDLE_VALUE)
{
else if (s[1] == quote || s[1] == '\\')
s++;
*p++ = '\\';
- *p++ = *s;
+ size_t cnt = isascii (*s) ? 1 : mbtowc (NULL, s, MB_CUR_MAX);
+ if (cnt <= 1 || cnt == (size_t)-1)
+ *p++ = *s;
+ else
+ {
+ --s;
+ while (cnt-- > 0)
+ *p++ = *++s;
+ }
}
if (*s == quote)
p--;
/* struct without updating SIZEOF_PER_PROCESS [it makes them think twice */
/* about changing it]. */
if (sizeof (per_process) != SIZEOF_PER_PROCESS)
- {
- api_fatal ("per_process sanity check failed");
- }
+ api_fatal ("per_process sanity check failed");
/* Make sure that the app and the dll are in sync. */
if (p->api_major > cygwin_version.api_major)
api_fatal ("cygwin DLL and APP are out of sync -- API version mismatch %d > %d",
p->api_major, cygwin_version.api_major);
-
- if (CYGWIN_VERSION_DLL_MAKE_COMBINED (p->dll_major, p->dll_minor) <=
- CYGWIN_VERSION_DLL_BAD_SIGNAL_MASK)
- signal_shift_subtract = 0;
}
child_info NO_COPY *child_proc_info = NULL;
-static MEMORY_BASIC_INFORMATION NO_COPY sm;
-#define CYGWIN_GUARD ((wincap.has_page_guard ()) ? \
- PAGE_EXECUTE_READWRITE|PAGE_GUARD : PAGE_NOACCESS)
+#define CYGWIN_GUARD (PAGE_EXECUTE_READWRITE | PAGE_GUARD)
-static void
-alloc_stack_hard_way (child_info_fork *ci, volatile char *b)
+void
+child_info_fork::alloc_stack_hard_way (volatile char *b)
{
void *new_stack_pointer;
MEMORY_BASIC_INFORMATION m;
void *newbase;
int newlen;
- LPBYTE curbot = (LPBYTE) sm.BaseAddress + sm.RegionSize;
- bool noguard;
+ bool guard;
+
+ if (!VirtualQuery ((LPCVOID) &b, &m, sizeof m))
+ api_fatal ("fork: couldn't get stack info, %E");
- if (ci->stacktop > (LPBYTE) sm.AllocationBase && ci->stacktop < curbot)
+ LPBYTE curbot = (LPBYTE) m.BaseAddress + m.RegionSize;
+
+ if (stacktop > (LPBYTE) m.AllocationBase && stacktop < curbot)
{
newbase = curbot;
- newlen = (LPBYTE) ci->stackbottom - (LPBYTE) curbot;
- noguard = 1;
+ newlen = (LPBYTE) stackbottom - (LPBYTE) curbot;
+ guard = false;
}
else
{
- newbase = ci->stacktop;
- newlen = (DWORD) ci->stackbottom - (DWORD) ci->stacktop;
- noguard = 0;
+ newbase = (LPBYTE) stacktop - (128 * 1024);
+ newlen = (LPBYTE) stackbottom - (LPBYTE) newbase;
+ guard = true;
}
+
if (!VirtualAlloc (newbase, newlen, MEM_RESERVE, PAGE_NOACCESS))
api_fatal ("fork: can't reserve memory for stack %p - %p, %E",
- ci->stacktop, ci->stackbottom);
-
- new_stack_pointer = (void *) ((LPBYTE) ci->stackbottom - ci->stacksize);
-
- if (!VirtualAlloc (new_stack_pointer, ci->stacksize, MEM_COMMIT,
+ stacktop, stackbottom);
+ new_stack_pointer = (void *) ((LPBYTE) stackbottom - (stacksize += 8192));
+ if (!VirtualAlloc (new_stack_pointer, stacksize, MEM_COMMIT,
PAGE_EXECUTE_READWRITE))
api_fatal ("fork: can't commit memory for stack %p(%d), %E",
- new_stack_pointer, ci->stacksize);
+ new_stack_pointer, stacksize);
if (!VirtualQuery ((LPCVOID) new_stack_pointer, &m, sizeof m))
api_fatal ("fork: couldn't get new stack info, %E");
- if (!noguard)
+
+ if (guard)
{
- m.BaseAddress = (LPVOID) ((DWORD) m.BaseAddress - 1);
+ m.BaseAddress = (LPBYTE) m.BaseAddress - 1;
if (!VirtualAlloc ((LPVOID) m.BaseAddress, 1, MEM_COMMIT,
CYGWIN_GUARD))
api_fatal ("fork: couldn't allocate new stack guard page %p, %E",
}
if (!VirtualQuery ((LPCVOID) m.BaseAddress, &m, sizeof m))
api_fatal ("fork: couldn't get new stack info, %E");
- ci->stacktop = m.BaseAddress;
+ stacktop = m.BaseAddress;
b[0] = '\0';
}
/* extend the stack prior to fork longjmp */
-static void
-alloc_stack (child_info_fork *ci)
+void
+child_info_fork::alloc_stack ()
{
volatile char * volatile esp;
__asm__ volatile ("movl %%esp,%0": "=r" (esp));
- if (_tlsbase != ci->stackbottom)
- alloc_stack_hard_way (ci, esp);
+ if (_tlsbase != stackbottom)
+ alloc_stack_hard_way (esp);
else
{
- char *stacktop = (char *) ci->stacktop - 4096;
- while (_tlstop >= stacktop)
+ char *st = (char *) stacktop - 4096;
+ while (_tlstop >= st)
esp = getstack (esp);
- ci->stacksize = 0;
+ stacksize = 0;
}
}
-#ifdef DEBUGGING
-void
+extern "C" void
break_here ()
{
+ static int NO_COPY sent_break;
+ if (!sent_break++)
+ DebugBreak ();
debug_printf ("break here");
}
-#endif
static void
initial_env ()
{
- char buf[CYG_MAX_PATH];
- if (GetEnvironmentVariable ("CYGWIN_TESTING", buf, sizeof (buf) - 1))
+ if (GetEnvironmentVariableA ("CYGWIN_TESTING", NULL, 0))
_cygwin_testing = 1;
#ifdef DEBUGGING
+ char buf[NT_MAX_PATH];
DWORD len;
- if (GetEnvironmentVariable ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
+ if (GetEnvironmentVariableA ("CYGWIN_SLEEP", buf, sizeof (buf) - 1))
{
DWORD ms = atoi (buf);
- buf[0] = '\0';
- len = GetModuleFileName (NULL, buf, CYG_MAX_PATH);
- console_printf ("Sleeping %d, pid %u %s\n", ms, GetCurrentProcessId (), buf);
+ console_printf ("Sleeping %d, pid %u %P\n", ms, GetCurrentProcessId ());
Sleep (ms);
if (!strace.active () && !dynamically_loaded)
strace.hello ();
}
- if (GetEnvironmentVariable ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
+ if (GetEnvironmentVariableA ("CYGWIN_DEBUG", buf, sizeof (buf) - 1))
{
- char buf1[CYG_MAX_PATH];
- len = GetModuleFileName (NULL, buf1, CYG_MAX_PATH);
+ char buf1[NT_MAX_PATH];
+ len = GetModuleFileName (NULL, buf1, NT_MAX_PATH);
strlwr (buf1);
strlwr (buf);
char *p = strpbrk (buf, ":=");
if (strstr (buf1, buf))
{
error_start_init (p);
+ jit_debug = true;
try_to_debug ();
console_printf ("*** Sending Break. gdb may issue spurious SIGTRAP message.\n");
- DebugBreak ();
break_here ();
}
}
get_cygwin_startup_info ()
{
STARTUPINFO si;
- char zeros[sizeof (child_proc_info->zero)] = {0};
GetStartupInfo (&si);
child_info *res = (child_info *) si.lpReserved2;
+
if (si.cbReserved2 < EXEC_MAGIC_SIZE || !res
- || memcmp (res->zero, zeros, sizeof (res->zero)) != 0)
+ || res->intro != PROC_MAGIC_GENERIC || res->magic != CHILD_INFO_MAGIC)
res = NULL;
else
{
if ((res->intro & OPROC_MAGIC_MASK) == OPROC_MAGIC_GENERIC)
multiple_cygwin_problem ("proc intro", res->intro, 0);
- else if (res->intro == PROC_MAGIC_GENERIC
- && res->magic != CHILD_INFO_MAGIC)
- multiple_cygwin_problem ("proc magic", res->magic,
- CHILD_INFO_MAGIC);
else if (res->cygheap != (void *) &_cygheap_start)
multiple_cygwin_problem ("cygheap base", (DWORD) res->cygheap,
(DWORD) &_cygheap_start);
multiple_cygwin_problem ("proc size", res->cb, should_be_cb);
else if (sizeof (fhandler_union) != res->fhandler_union_cb)
multiple_cygwin_problem ("fhandler size", res->fhandler_union_cb, sizeof (fhandler_union));
- if (res->straced)
+ if (res->isstraced ())
{
res->ready (false);
-#if 0
- DWORD prio = GetThreadPriority (GetCurrentThread ());
- SetThreadPriority (GetCurrentThread (), THREAD_PRIORITY_IDLE);
-#endif
for (unsigned i = 0; !being_debugged () && i < 10000; i++)
low_priority_sleep (0);
-#if 0
- SetThreadPriority (GetCurrentThread (), prio);
-#endif
strace.hello ();
}
break;
child_info_fork::handle_fork ()
{
cygheap_fixup_in_child (false);
- memory_init ();
- set_myself (NULL);
+ memory_init (false);
+ myself.thisproc (NULL);
+ myself->uid = cygheap->user.real_uid;
+ myself->gid = cygheap->user.real_gid;
+
child_copy (parent, false,
"dll data", dll_data_start, dll_data_end,
"dll bss", dll_bss_start, dll_bss_end,
api_fatal ("recreate_mmaps_after_fork_failed");
}
+void
+child_info_spawn::handle_spawn ()
+{
+ extern void fixup_lockf_after_exec ();
+ HANDLE h;
+ cygheap_fixup_in_child (true);
+ memory_init (false);
+ if (!moreinfo->myself_pinfo ||
+ !DuplicateHandle (hMainProc, moreinfo->myself_pinfo, hMainProc, &h, 0,
+ FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
+ h = NULL;
+ myself.thisproc (h);
+ __argc = moreinfo->argc;
+ __argv = moreinfo->argv;
+ envp = moreinfo->envp;
+ envc = moreinfo->envc;
+ if (!dynamically_loaded)
+ cygheap->fdtab.fixup_after_exec ();
+ if (__stdin >= 0)
+ cygheap->fdtab.move_fd (__stdin, 0);
+ if (__stdout >= 0)
+ cygheap->fdtab.move_fd (__stdout, 1);
+ cygheap->user.groups.clear_supp ();
+
+ ready (true);
+
+ /* Need to do this after debug_fixup_after_fork_exec or DEBUGGING handling of
+ handles might get confused. */
+ CloseHandle (child_proc_info->parent);
+ child_proc_info->parent = NULL;
+
+ signal_fixup_after_exec ();
+ if (moreinfo->old_title)
+ {
+ old_title = strcpy (title_buf, moreinfo->old_title);
+ cfree (moreinfo->old_title);
+ }
+ fixup_lockf_after_exec ();
+}
+
+#if 0
+/* Setting the TS-aware flag in the application's PE header is sufficient.
+ Just keep this in as a reminder. */
+
+static DEP_SYSTEM_POLICY_TYPE dep_system_policy = (DEP_SYSTEM_POLICY_TYPE) -1;
+
+static void
+disable_dep ()
+{
+ DWORD ppolicy;
+ BOOL perm;
+
+ if (dep_system_policy < 0)
+ {
+ dep_system_policy = GetSystemDEPPolicy ();
+ debug_printf ("DEP System Policy: %d", (int) dep_system_policy);
+ }
+ if (dep_system_policy < OptIn)
+ return;
+ if (!GetProcessDEPPolicy (hMainProc, &ppolicy, &perm))
+ {
+ debug_printf ("GetProcessDEPPolicy: %E");
+ return;
+ }
+ debug_printf ("DEP Process Policy: %d (permanent = %d)", ppolicy, perm);
+ if (ppolicy > 0 && !perm && !SetProcessDEPPolicy (0))
+ debug_printf ("SetProcessDEPPolicy: %E");
+}
+#endif
+
void __stdcall
dll_crt0_0 ()
{
init_global_security ();
+ initial_env ();
+
+ SetErrorMode (SEM_FAILCRITICALERRORS | SEM_NOGPFAULTERRORBOX);
+
+ /* Initialize signal processing here, early, in the hopes that the creation
+ of a thread early in the process will cause more predictability in memory
+ layout for the main thread. */
+ if (!dynamically_loaded)
+ sigproc_init ();
+
lock_process::init ();
- init_console_handler (TRUE);
_impure_ptr = _GLOBAL_REENT;
_impure_ptr->_stdin = &_impure_ptr->__sf[0];
_impure_ptr->_stdout = &_impure_ptr->__sf[1];
_impure_ptr->_current_locale = "C";
user_data->impure_ptr = _impure_ptr;
user_data->impure_ptr_ptr = &_impure_ptr;
- wincap.init ();
- initial_env ();
- mmap_init ();
if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
GetCurrentProcess (), &hMainProc, 0, FALSE,
DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
&hMainThread, 0, false, DUPLICATE_SAME_ACCESS);
- if (wincap.has_security ())
- OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
- SetErrorMode (SEM_FAILCRITICALERRORS);
+ OpenProcessToken (hMainProc, MAXIMUM_ALLOWED, &hProcToken);
+ set_cygwin_privileges (hProcToken);
+
device::init ();
do_global_ctors (&__CTOR_LIST__, 1);
cygthread::init ();
child_proc_info = get_cygwin_startup_info ();
if (!child_proc_info)
- memory_init ();
+ memory_init (true);
else
{
cygwin_user_h = child_proc_info->user_h;
break;
case _PROC_SPAWN:
case _PROC_EXEC:
- HANDLE h;
- cygheap_fixup_in_child (true);
- memory_init ();
- if (!spawn_info->moreinfo->myself_pinfo ||
- !DuplicateHandle (hMainProc, spawn_info->moreinfo->myself_pinfo,
- hMainProc, &h, 0, FALSE,
- DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
- h = NULL;
- set_myself (h);
- if (child_proc_info->type != _PROC_FORK)
- child_proc_info->ready (true);
- __argc = spawn_info->moreinfo->argc;
- __argv = spawn_info->moreinfo->argv;
- envp = spawn_info->moreinfo->envp;
- envc = spawn_info->moreinfo->envc;
- if (!dynamically_loaded)
- cygheap->fdtab.fixup_after_exec ();
- signal_fixup_after_exec ();
- if (spawn_info->moreinfo->old_title)
- {
- old_title = strcpy (title_buf, spawn_info->moreinfo->old_title);
- cfree (spawn_info->moreinfo->old_title);
- }
+ spawn_info->handle_spawn ();
break;
}
}
+ user_data->threadinterface->Init ();
+
_cygtls::init ();
/* Initialize events */
events_init ();
+ tty_list::init_session ();
- cygheap->cwd.init ();
+#if 0
+ /* Setting the TS-aware flag in the application's PE header is sufficient.
+ Just keep this in as a reminder. */
+
+ /* The disable_dep function disables DEP for all Cygwin processes if
+ the process runs on a Windows Server 2008 with Terminal Services
+ installed. This combination (TS+DEP) breaks *some* Cygwin
+ applications. The Terminal Service specific DLL tsappcmp.dll
+ changes the page protection of some pages in the application's text
+ segment from PAGE_EXECUTE_WRITECOPY to PAGE_WRITECOPY for no
+ apparent reason. This occurs before any Cygwin or applicaton code
+ had a chance to run. MS has no explanation for this so far, but is
+ rather busy trying to avoid giving support for this problem (as of
+ 2008-11-11).
+
+ Unfortunately disabling DEP seems to have a not negligible
+ performance hit. In the long run, either MS has to fix their
+ problem, or we have to find a better workaround, if any exists.
+ Idle idea: Adding EXECUTE protection to all text segment pages? */
+ if (wincap.ts_has_dep_problem ())
+ disable_dep ();
+#endif
- /* Late duplicate simplifies tweaking the process token in uinfo.cc. */
- if (wincap.has_security ())
- DuplicateTokenEx (hProcToken, MAXIMUM_ALLOWED, NULL,
- SecurityImpersonation, TokenImpersonation,
- &hProcImpToken);
debug_printf ("finished dll_crt0_0 initialization");
}
various special cases when Cygwin DLL is being runtime loaded (as
opposed to being link-time loaded by Cygwin apps) from a non
cygwin app via LoadLibrary. */
-static void
-dll_crt0_1 (char *)
+void
+dll_crt0_1 (void *)
{
+ if (dynamically_loaded)
+ sigproc_init ();
check_sanity_and_sync (user_data);
+
+ /* Initialize malloc and then call user_shared_initialize since it relies
+ on a functioning malloc and it's possible that the user's program may
+ have overridden malloc. We only know about that at this stage,
+ unfortunately. */
malloc_init ();
+ user_shared_initialize ();
+
#ifdef CGF
int i = 0;
const int n = 2 * 1024 * 1024;
small_printf ("cmalloc returns %p\n", cmalloc (HEAP_STR, n));
#endif
- user_data->resourcelocks->Init ();
- user_data->threadinterface->Init ();
ProtectHandle (hMainProc);
ProtectHandle (hMainThread);
+ cygheap->cwd.init ();
+
/* Initialize pthread mainthread when not forked and it is safe to call new,
otherwise it is reinitalized in fixup_after_fork */
if (!in_forkee)
strace.microseconds ();
#endif
- create_signal_arrived ();
+ create_signal_arrived (); /* FIXME: move into wait_sig? */
/* Initialize debug muto, if DLL is built with --enable-debugging.
Need to do this before any helper threads start. */
{
_tlsbase = (char *) fork_info->stackbottom;
_tlstop = (char *) fork_info->stacktop;
+ _my_tls.init_exception_handler (_cygtls::handle_exceptions);
}
+
longjmp (fork_info->jmp, true);
}
fork_init ();
}
#endif
-
- /* Initialize our process table entry. */
pinfo_init (envp, envc);
- /* Can be set only after environment has been initialized. */
- if (wincap.has_security ())
- set_cygwin_privileges (hProcImpToken);
-
if (!old_title && GetConsoleTitle (title_buf, TITLESIZE))
- old_title = title_buf;
+ old_title = title_buf;
/* Allocate cygheap->fdtab */
dtable_init ();
- /* Initialize user info. */
- uinfo_init ();
+ uinfo_init (); /* initialize user info */
- /* Initialize signal/subprocess handling. */
- sigproc_init ();
+ wait_for_sigthread ();
+ extern DWORD threadfunc_ix;
+ if (!threadfunc_ix)
+ system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
/* Connect to tty. */
- tty_init ();
+ tty::init_session ();
if (!__argc)
{
- char *line = GetCommandLineA ();
- line = strcpy ((char *) alloca (strlen (line) + 1), line);
-
- if (current_codepage == oem_cp)
- CharToOemA (line, line);
+ PWCHAR wline = GetCommandLineW ();
+ size_t size = sys_wcstombs (NULL, 0, wline);
+ char *line = (char *) alloca (size);
+ sys_wcstombs (line, size, wline);
/* Scan the command line and build argv. Expand wildcards if not
called from another cygwin process. */
win32 style. */
if ((strchr (__argv[0], ':')) || (strchr (__argv[0], '\\')))
{
- char *new_argv0 = (char *) malloc (CYG_MAX_PATH);
- cygwin_conv_to_posix_path (__argv[0], new_argv0);
+ char *new_argv0 = (char *) malloc (NT_MAX_PATH);
+ cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_RELATIVE, __argv[0],
+ new_argv0, NT_MAX_PATH);
__argv[0] = (char *) realloc (new_argv0, strlen (new_argv0) + 1);
}
}
if (__progname)
{
char *cp = strchr (__progname, '\0') - 4;
- if (cp > __progname && strcasematch (cp, ".exe"))
+ if (cp > __progname && ascii_strcasematch (cp, ".exe"))
*cp = '\0';
}
/* 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. */
- wait_for_sigthread ();
ld_preload ();
+ /* Reset current application locale to "C" per POSIX */
+ _setlocale_r (_REENT, LC_CTYPE, "C");
if (user_data->main)
cygwin_exit (user_data->main (__argc, __argv, *user_data->envptr));
+ __asm__ (" \n\
+ .global __cygwin_exit_return \n\
+__cygwin_exit_return: \n\
+");
}
-struct _reent *
-initialize_main_tls (char *padding)
-{
- if (!_main_tls)
- {
- _main_tls = &_my_tls;
- _main_tls->init_thread (padding, NULL);
- }
- return &_main_tls->local_clib;
-}
-
-/* Wrap the real one, otherwise gdb gets confused about
- two symbols with the same name, but different addresses.
-
- UPTR is a pointer to global data that lives on the libc side of the
- line [if one distinguishes the application from the dll]. */
-
extern "C" void __stdcall
_dll_crt0 ()
{
- extern DWORD threadfunc_ix;
- extern HANDLE sync_startup;
- if (sync_startup != INVALID_HANDLE_VALUE)
- {
- WaitForSingleObject (sync_startup, INFINITE);
- CloseHandle (sync_startup);
- }
-
- sync_startup = NULL;
- if (!threadfunc_ix)
- system_printf ("internal error: couldn't determine location of thread function on stack. Expect signal problems.");
-
main_environ = user_data->envptr;
-#if 0
- *main_environ = NULL;
-#endif
-
- char padding[CYGTLS_PADSIZE];
-
-debug_printf ("in_forkee %d, fork_info %p", in_forkee, fork_info);
if (in_forkee)
- alloc_stack (fork_info);
+ fork_info->alloc_stack ();
else
__sinit (_impure_ptr);
- initialize_main_tls (padding);
- dll_crt0_1 (padding);
+ _main_tls = &_my_tls;
+ _main_tls->call ((DWORD (*) (void *, void *)) dll_crt0_1, NULL);
}
void
static char **envp;
static int _fmode;
- if (!DuplicateHandle (GetCurrentProcess (), GetCurrentProcess (),
- GetCurrentProcess (), &hMainProc, 0, FALSE,
- DUPLICATE_SAME_ACCESS))
- hMainProc = GetCurrentProcess ();
-
- DuplicateHandle (hMainProc, GetCurrentThread (), hMainProc,
- &hMainThread, 0, FALSE, DUPLICATE_SAME_ACCESS);
user_data->magic_biscuit = sizeof (per_process);
user_data->envptr = &envp;
user_data->fmode_ptr = &_fmode;
- main_environ = user_data->envptr;
-#if 0
- *main_environ = NULL;
-#endif
- initialize_main_tls((char *)&_my_tls);
- dll_crt0_1 (NULL);
+ _dll_crt0 ();
}
extern "C" void
__main (void)
{
+ /* Ordering is critical here. DLL ctors have already been
+ run as they were being loaded, so we should stack the
+ queued call to DLL dtors now. */
+ atexit (dll_global_dtors);
do_global_ctors (user_data->ctors, false);
+ /* Now we have run global ctors, register their dtors. */
atexit (do_global_dtors);
+ /* At exit, global dtors will run first, so the app can still
+ use shared library functions while terminating; then the
+ DLLs will be destroyed; finally newlib will shut down stdio
+ and terminate itself. */
}
-exit_states NO_COPY exit_state;
-
void __stdcall
do_exit (int status)
{
lock_process until_exit (true);
- if (exit_state < ES_GLOBAL_DTORS)
- {
- exit_state = ES_GLOBAL_DTORS;
- dll_global_dtors ();
- }
-
if (exit_state < ES_EVENTS_TERMINATE)
{
exit_state = ES_EVENTS_TERMINATE;
/* Kill orphaned children on group leader exit */
if (myself->has_pgid_children && myself->pid == myself->pgid)
{
- siginfo_t si;
+ siginfo_t si = {0};
si.si_signo = -SIGHUP;
si.si_code = SI_KERNEL;
- si.si_pid = si.si_uid = si.si_errno = 0;
sigproc_printf ("%d == pgrp %d, send SIG{HUP,CONT} to stopped children",
myself->pid, myself->pgid);
kill_pgrp (myself->pgid, si);
if (exit_state < ES_TTY_TERMINATE)
{
exit_state = ES_TTY_TERMINATE;
- tty_terminate ();
+ cygwin_shared->tty.terminate ();
}
myself.exit (n);
extern "C" void
cygwin_exit (int n)
{
- dll_global_dtors ();
if (atexit_lock)
atexit_lock.acquire ();
exit (n);
va_list ap;
va_start (ap, fmt);
- int n = __small_sprintf (buf, "%P: *** fatal error - ", cygwin_pid (GetCurrentProcessId ()));
+ int n = __small_sprintf (buf, "%P: *** fatal error - ");
__small_vsprintf (buf + n, fmt, ap);
va_end (ap);
strace.prntf (_STRACE_SYSTEM, NULL, "%s", buf);
#ifdef DEBUGGING
try_to_debug ();
#endif
- myself.exit (1);
+ myself.exit (__api_fatal_exit_val);
}
void
return;
}
- char buf[1024];
- if (GetEnvironmentVariable ("CYGWIN_MISMATCH_OK", buf, sizeof (buf)))
+ if (GetEnvironmentVariableA ("CYGWIN_MISMATCH_OK", NULL, 0))
return;
if (CYGWIN_VERSION_MAGIC_VERSION (magic_version) == version)
void __stdcall
cygbench (const char *s)
{
- char buf[1024];
- if (GetEnvironmentVariable ("CYGWIN_BENCH", buf, sizeof (buf)))
+ if (GetEnvironmentVariableA ("CYGWIN_BENCH", NULL, 0))
small_printf ("%05d ***** %s : %10d\n", GetCurrentProcessId (), s, strace.microseconds ());
}
#endif