/* dcrt0.cc -- essentially the main() for the Cygwin dll
- Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
- 2006, 2007, 2008 Red Hat, Inc.
+ Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
+ 2007, 2008, 2009
+ Red Hat, Inc.
This file is part of Cygwin.
#include <stdlib.h>
#include "glob.h"
#include <ctype.h>
+#include <locale.h>
+#include "environ.h"
#include "sigproc.h"
#include "pinfo.h"
#include "cygerrno.h"
#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;
-
-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;
-
-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 = &__cygwin_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, 0},
- /* 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];
-int NO_COPY __api_fatal_exit_val = 1;
-char *old_title;
-char title_buf[TITLESIZE + 1];
+bool NO_COPY jit_debug;
static void
do_global_dtors ()
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--;
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");
break_here ();
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;
extern void fixup_lockf_after_exec ();
HANDLE h;
cygheap_fixup_in_child (true);
- memory_init ();
+ memory_init (false);
if (!moreinfo->myself_pinfo ||
!DuplicateHandle (hMainProc, moreinfo->myself_pinfo, hMainProc, &h, 0,
FALSE, DUPLICATE_SAME_ACCESS | DUPLICATE_CLOSE_SOURCE))
h = NULL;
- set_myself (h);
+ myself.thisproc (h);
__argc = moreinfo->argc;
__argv = moreinfo->argv;
envp = moreinfo->envp;
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 ()
{
/* 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. */
- sigproc_init ();
+ if (!dynamically_loaded)
+ sigproc_init ();
lock_process::init ();
_impure_ptr = _GLOBAL_REENT;
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;
events_init ();
tty_list::init_session ();
- if (dynamically_loaded)
- {
- /* When dynamically loaded. we must initialize the user shared memory
- entirely here since dll_crt0_1 will not be called. Stuff in
- user_shared_initialize_1 relies on malloc and cygtls being available
- and the initialization isn't finished without calling it. In the
- non-dynamical case this is called in dll_crt0_1, because malloc_init
- has to test for overloaded malloc functionality in the application.
- That's not an issue when cygwin is loaded dynamically. It will just
- use its own malloc area. */
- malloc_init ();
- user_shared_initialize_1 ();
- }
+#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
debug_printf ("finished dll_crt0_0 initialization");
}
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;
ProtectHandle (hMainProc);
ProtectHandle (hMainThread);
- user_shared_initialize_1 ();
-
cygheap->cwd.init ();
/* Initialize pthread mainthread when not forked and it is safe to call new,
do this for noncygwin case since the signal thread is blocked due to
LoadLibrary serialization. */
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\
+");
}
extern "C" void __stdcall
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;
extern "C" void
cygwin_exit (int n)
{
- dll_global_dtors ();
if (atexit_lock)
atexit_lock.acquire ();
exit (n);