OSDN Git Service

* globals.cc (enum exit_states::ES_GLOBAL_DTORS): Delete.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / dcrt0.cc
index 5fbf2df..9cff06f 100644 (file)
@@ -1,7 +1,8 @@
 /* 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.
 
@@ -15,6 +16,8 @@ details. */
 #include <stdlib.h>
 #include "glob.h"
 #include <ctype.h>
+#include <locale.h>
+#include "environ.h"
 #include "sigproc.h"
 #include "pinfo.h"
 #include "cygerrno.h"
@@ -36,82 +39,16 @@ details. */
 
 #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 ()
@@ -294,7 +231,15 @@ globify (char *word, char **&argv, int &argc, int &argvlen)
            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--;
@@ -556,6 +501,7 @@ initial_env ()
       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 ();
@@ -628,8 +574,8 @@ void
 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;
 
@@ -655,12 +601,12 @@ child_info_spawn::handle_spawn ()
   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;
@@ -689,6 +635,36 @@ child_info_spawn::handle_spawn ()
   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 ()
 {
@@ -700,7 +676,8 @@ 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;
@@ -728,7 +705,7 @@ dll_crt0_0 ()
 
   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;
@@ -752,19 +729,28 @@ dll_crt0_0 ()
   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");
 }
@@ -776,8 +762,17 @@ dll_crt0_0 ()
 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;
@@ -788,8 +783,6 @@ dll_crt0_1 (void *)
   ProtectHandle (hMainProc);
   ProtectHandle (hMainThread);
 
-  user_shared_initialize_1 ();
-
   cygheap->cwd.init ();
 
   /* Initialize pthread mainthread when not forked and it is safe to call new,
@@ -940,8 +933,14 @@ dll_crt0_1 (void *)
      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
@@ -994,12 +993,19 @@ cygwin_dll_init ()
 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)
 {
@@ -1016,12 +1022,6 @@ 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;
@@ -1117,7 +1117,6 @@ cygwin_atexit (void (*function)(void))
 extern "C" void
 cygwin_exit (int n)
 {
-  dll_global_dtors ();
   if (atexit_lock)
     atexit_lock.acquire ();
   exit (n);