mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-15 11:00:04 +08:00
a939686807
(child_info::retry): Move here from fork subclass. (child_info::exit_code): New field. (child_info::retry_count): Max retry count for process start. (child_info::proc_retry): Declare new function. (child_info_fork::retry): Move to parent. (child_info_fork::fork_retry): Ditto. * dcrt0.cc (child_info::fork_retry): Rename and move. (child_info_fork::handle_failure): Move. (dll_crt0_0): Initialize console handler based on whether we have a controlling tty or not. Avoid nonsensical check for fork where it can never occur. * environ.cc (set_proc_retry): Rename from set_fork_retry. Set retry_count in child_info. (parse_thing): Reflect above change. * exceptions.cc (dummy_ctrl_c_handler): Remove unused variable name. (ctrl_c_handler): Always return TRUE for the annoying CTRL_LOGOFF_EVENT. * fhandler_termios.cc (fhandler_termios::tcsetpgrp): Remove call to init_console_handler. * fhandler_tty.cc (fhandler_tty_slave::open): Just call mange_console_count here and let it decide what to do with initializing console control handling. * fork.cc (fork_retry): Remove definition. (frok::parent): Define static errbuf and use in error messages (not thread safe yet). Close pi.hThread as soon as possible. Protect pi.hProcess as soon as possible. Don't set retry_count. That happens automatically in the constructor now. Accommodate name change from fork_retry to proc_retry. * init.cc (dll_entry): Turn off ctrl-c handling early until we know how it is supposed to be handled. * pinfo.cc (_pinfo::dup_proc_pipe): Remember original proc pipe value for failure error message. Tweak debug message slightly. * sigproc.cc (child_info::retry_count): Define. (child_info::child_info): Initialize retry count. (child_info::sync): Set exit code if process dies before synchronization. (child_info::proc_retry): Rename from child_info_fork::fork_retry. Use previously derived exit code. Be more defensive about what is classified as an error exit. (child_info_fork::handle_failure): Move here from dcrt0.cc. * spawn.cc (spawn_guts): Maintain error mode when starting new process to avoid annoying pop ups. Move deimpersonate call within new loop. Move envblock freeing to end. Loop if process dies prematurely with bad exit code. * syscalls.cc (init_console_handler): Remove hopefully unneeded call to init_console_handler.
164 lines
4.1 KiB
C++
164 lines
4.1 KiB
C++
/* init.cc
|
|
|
|
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
|
|
2006 Red Hat, Inc.
|
|
|
|
This file is part of Cygwin.
|
|
|
|
This software is a copyrighted work licensed under the terms of the
|
|
Cygwin license. Please consult the file "CYGWIN_LICENSE" for
|
|
details. */
|
|
|
|
#include "winsup.h"
|
|
#include <stdlib.h>
|
|
#include "thread.h"
|
|
#include "perprocess.h"
|
|
#include "cygtls.h"
|
|
#include "pinfo.h"
|
|
#include <ntdef.h>
|
|
#include "ntdll.h"
|
|
|
|
int NO_COPY dynamically_loaded;
|
|
static char NO_COPY *search_for = (char *) cygthread::stub;
|
|
unsigned threadfunc_ix[8] __attribute__((section (".cygwin_dll_common"), shared));
|
|
extern cygthread *hwait_sig;
|
|
|
|
#define OLDFUNC_OFFSET -1
|
|
|
|
static void WINAPI
|
|
threadfunc_fe (VOID *arg)
|
|
{
|
|
(void)__builtin_return_address(1);
|
|
asm volatile ("andl $-16,%%esp" ::: "%esp");
|
|
_cygtls::call ((DWORD (*) (void *, void *)) (((char **) _tlsbase)[OLDFUNC_OFFSET]), arg);
|
|
}
|
|
|
|
/* If possible, redirect the thread entry point to a cygwin routine which
|
|
adds tls stuff to the stack. */
|
|
static void
|
|
munge_threadfunc ()
|
|
{
|
|
int i;
|
|
char **ebp = (char **) __builtin_frame_address (0);
|
|
if (!threadfunc_ix[0])
|
|
{
|
|
char **peb;
|
|
char **top = (char **) _tlsbase;
|
|
for (peb = ebp, i = 0; peb < top && i < 7; peb++)
|
|
if (*peb == search_for)
|
|
threadfunc_ix[i++] = peb - ebp;
|
|
if (0 && !threadfunc_ix[0])
|
|
{
|
|
try_to_debug ();
|
|
return;
|
|
}
|
|
}
|
|
|
|
if (threadfunc_ix[0])
|
|
{
|
|
char *threadfunc = ebp[threadfunc_ix[0]];
|
|
if (!search_for || threadfunc == search_for)
|
|
{
|
|
search_for = NULL;
|
|
for (i = 0; threadfunc_ix[i]; i++)
|
|
ebp[threadfunc_ix[i]] = (char *) threadfunc_fe;
|
|
((char **) _tlsbase)[OLDFUNC_OFFSET] = threadfunc;
|
|
}
|
|
}
|
|
}
|
|
|
|
inline static void
|
|
respawn_wow64_process ()
|
|
{
|
|
NTSTATUS ret;
|
|
PROCESS_BASIC_INFORMATION pbi;
|
|
HANDLE parent;
|
|
|
|
BOOL is_wow64_proc = TRUE; /* Opt on the safe side. */
|
|
|
|
/* Unfortunately there's no simpler way to retrieve the
|
|
parent process in NT, as far as I know. Hints welcome. */
|
|
ret = NtQueryInformationProcess (GetCurrentProcess (),
|
|
ProcessBasicInformation,
|
|
(PVOID) &pbi,
|
|
sizeof pbi, NULL);
|
|
if (ret == STATUS_SUCCESS
|
|
&& (parent = OpenProcess (PROCESS_QUERY_INFORMATION,
|
|
FALSE,
|
|
pbi.InheritedFromUniqueProcessId)))
|
|
{
|
|
IsWow64Process (parent, &is_wow64_proc);
|
|
CloseHandle (parent);
|
|
}
|
|
|
|
/* The parent is a real 64 bit process? Respawn! */
|
|
if (!is_wow64_proc)
|
|
{
|
|
PROCESS_INFORMATION pi;
|
|
STARTUPINFO si;
|
|
DWORD ret = 0;
|
|
|
|
GetStartupInfo (&si);
|
|
if (!CreateProcessA (NULL, GetCommandLineA (), NULL, NULL, TRUE,
|
|
CREATE_DEFAULT_ERROR_MODE
|
|
| GetPriorityClass (GetCurrentProcess ()),
|
|
NULL, NULL, &si, &pi))
|
|
api_fatal ("Failed to create process <%s>, %E", GetCommandLineA ());
|
|
CloseHandle (pi.hThread);
|
|
if (WaitForSingleObject (pi.hProcess, INFINITE) == WAIT_FAILED)
|
|
api_fatal ("Waiting for process %d failed, %E", pi.dwProcessId);
|
|
GetExitCodeProcess (pi.hProcess, &ret);
|
|
CloseHandle (pi.hProcess);
|
|
ExitProcess (ret);
|
|
}
|
|
}
|
|
|
|
extern void __stdcall dll_crt0_0 ();
|
|
|
|
HMODULE NO_COPY cygwin_hmodule;
|
|
bool in_dllentry;
|
|
|
|
extern "C" BOOL WINAPI
|
|
dll_entry (HANDLE h, DWORD reason, void *static_load)
|
|
{
|
|
BOOL wow64_test_stack_marker;
|
|
|
|
in_dllentry = true;
|
|
|
|
switch (reason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
wincap.init ();
|
|
init_console_handler (false);
|
|
|
|
cygwin_hmodule = (HMODULE) h;
|
|
dynamically_loaded = (static_load == NULL);
|
|
|
|
/* Is the stack at an unusual address? This is, an address which
|
|
is in the usual space occupied by the process image, but below
|
|
the auto load address of DLLs?
|
|
Check if we're running in WOW64 on a 64 bit machine *and* are
|
|
spawned by a genuine 64 bit process. If so, respawn. */
|
|
if (wincap.is_wow64 ()
|
|
&& &wow64_test_stack_marker >= (PBOOL) 0x400000
|
|
&& &wow64_test_stack_marker <= (PBOOL) 0x10000000)
|
|
respawn_wow64_process ();
|
|
|
|
dll_crt0_0 ();
|
|
break;
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
case DLL_THREAD_ATTACH:
|
|
if (hwait_sig)
|
|
munge_threadfunc ();
|
|
break;
|
|
case DLL_THREAD_DETACH:
|
|
if (hwait_sig)
|
|
_my_tls.remove (0);
|
|
break;
|
|
}
|
|
|
|
in_dllentry = false;
|
|
return TRUE;
|
|
}
|