Skip to content
Permalink
Browse files

Merge branch 'ctrl-c'

This is part two of the Ctrl+C story, where part one is
git-for-windows/MSYS2-packages@f4fda0f.

Part one took care of extending the signal handling in the MSYS2 runtime
such that non-MSYS2 processes "receive" a SIGINT by injecting a remote
thread that runs kernel32!CtrlRoutine as if GenerateConsoleCtrlHandler()
had been called (but in contrast to the latter, only one process is
targeted at a time, not every process attached to the same Console) into
the process that needs to be interrupted as well as into all of the
spawned child processes.

Part two now takes care of removing the misguided "kill all spawned
children" atexit() handler, and it also installs a ConsoleCtrl handler
to run Git's SIGINT handlers, such as the one waiting for the pager to
exit.

Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>
  • Loading branch information...
dscho committed Apr 23, 2018
2 parents 20d8479 + 1cbdbd7 commit df8884cbc5c39073848ddf2058bafeea1188312b
Showing with 13 additions and 45 deletions.
  1. +13 −45 compat/mingw.c
@@ -1528,39 +1528,6 @@ struct pinfo_t {
static struct pinfo_t *pinfo = NULL;
CRITICAL_SECTION pinfo_cs;

#ifndef SIGRTMAX
#define SIGRTMAX 63
#endif

static void kill_child_processes_on_signal(void)
{
DWORD status;

/*
* Only continue if the process was terminated by a signal, as
* indicated by the exit status (128 + sig_no).
*
* As we are running in an atexit() handler, the exit code has been
* set at this stage by the ExitProcess() function already.
*/
if (!GetExitCodeProcess(GetCurrentProcess(), &status) ||
status <= 128 || status > 128 + SIGRTMAX)
return;

EnterCriticalSection(&pinfo_cs);

while (pinfo) {
struct pinfo_t *info = pinfo;
pinfo = pinfo->next;
if (exit_process(info->proc, status))
/* the handle is still valid in case of error */
CloseHandle(info->proc);
free(info);
}

LeaveCriticalSection(&pinfo_cs);
}

static int is_msys2_sh(const char *cmd)
{
if (cmd && !strcmp(cmd, "sh")) {
@@ -1593,7 +1560,7 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
const char *dir, const char *prepend_cmd,
int fhin, int fhout, int fherr)
{
static int atexit_handler_initialized, restrict_handle_inheritance = 1;
static int restrict_handle_inheritance = 1;
STARTUPINFOEXW si;
PROCESS_INFORMATION pi;
LPPROC_THREAD_ATTRIBUTE_LIST attr_list = NULL;
@@ -1609,17 +1576,6 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **deltaen
const char *(*quote_arg)(const char *arg) =
is_msys2_sh(*argv) ? quote_arg_msys2 : quote_arg_msvc;

if (!atexit_handler_initialized) {
atexit_handler_initialized = 1;
/*
* On Windows, there is no POSIX signaling. Instead, we inject
* a thread calling ExitProcess(128 + sig_no); and that calls
* the *atexit* handlers. Catch this condition and kill child
* processes with the same signal.
*/
atexit(kill_child_processes_on_signal);
}

do_unset_environment_variables();

/* Determine whether or not we are associated to a console */
@@ -3338,6 +3294,14 @@ static void adjust_symlink_flags(void)

}

static BOOL handle_ctrl_c(DWORD ctrl_type)
{
if (ctrl_type != CTRL_C_EVENT)
return FALSE; /* we did not handle this */
mingw_raise(SIGINT);
return TRUE; /* we did handle this */
}

#if defined(_MSC_VER)

#ifdef _DEBUG
@@ -3376,6 +3340,8 @@ int msc_startup(int argc, wchar_t **w_argv, wchar_t **w_env)
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
#endif

SetConsoleCtrlHandler(handle_ctrl_c, TRUE);

fsync_object_files = 1;
maybe_redirect_std_handles();
adjust_symlink_flags();
@@ -3444,6 +3410,8 @@ void mingw_startup(void)
wchar_t **wenv, **wargv;
_startupinfo si;

SetConsoleCtrlHandler(handle_ctrl_c, TRUE);

fsync_object_files = 1;
maybe_redirect_std_handles();
adjust_symlink_flags();

0 comments on commit df8884c

Please sign in to comment.
You can’t perform that action at this time.