mingw: use real pid
The Windows port have so far been using process handles in place of PID. However, this is not work consistent with what getpid returns. PIDs are system-global identifiers, but process handles are local to a process. Using PIDs instead of process handles allows, for instance, a user to kill a hung process with the Task Manager, something that would have been impossible with process handles. Change the code to use the real PID, and use OpenProcess to get a process-handle. Store the PID and the process handle in a linked list protected by a critical section, so we can safely close the process handle later. Linked list code written by Pat Thoyts. Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com> Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net> Signed-off-by: Junio C Hamano <gitster@pobox.com>
This commit is contained in:
parent
bb34c5aabe
commit
52de4db579
@ -702,6 +702,14 @@ static int env_compare(const void *a, const void *b)
|
||||
return strcasecmp(*ea, *eb);
|
||||
}
|
||||
|
||||
struct pinfo_t {
|
||||
struct pinfo_t *next;
|
||||
pid_t pid;
|
||||
HANDLE proc;
|
||||
} pinfo_t;
|
||||
struct pinfo_t *pinfo = NULL;
|
||||
CRITICAL_SECTION pinfo_cs;
|
||||
|
||||
static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
|
||||
const char *dir,
|
||||
int prepend_cmd, int fhin, int fhout, int fherr)
|
||||
@ -794,7 +802,26 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
|
||||
return -1;
|
||||
}
|
||||
CloseHandle(pi.hThread);
|
||||
return (pid_t)pi.hProcess;
|
||||
|
||||
/*
|
||||
* The process ID is the human-readable identifier of the process
|
||||
* that we want to present in log and error messages. The handle
|
||||
* is not useful for this purpose. But we cannot close it, either,
|
||||
* because it is not possible to turn a process ID into a process
|
||||
* handle after the process terminated.
|
||||
* Keep the handle in a list for waitpid.
|
||||
*/
|
||||
EnterCriticalSection(&pinfo_cs);
|
||||
{
|
||||
struct pinfo_t *info = xmalloc(sizeof(struct pinfo_t));
|
||||
info->pid = pi.dwProcessId;
|
||||
info->proc = pi.hProcess;
|
||||
info->next = pinfo;
|
||||
pinfo = info;
|
||||
}
|
||||
LeaveCriticalSection(&pinfo_cs);
|
||||
|
||||
return (pid_t)pi.dwProcessId;
|
||||
}
|
||||
|
||||
static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
|
||||
@ -1518,6 +1545,50 @@ char *getpass(const char *prompt)
|
||||
return strbuf_detach(&buf, NULL);
|
||||
}
|
||||
|
||||
pid_t waitpid(pid_t pid, int *status, unsigned options)
|
||||
{
|
||||
HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
|
||||
FALSE, pid);
|
||||
if (!h) {
|
||||
errno = ECHILD;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (options == 0) {
|
||||
struct pinfo_t **ppinfo;
|
||||
if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
|
||||
CloseHandle(h);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (status)
|
||||
GetExitCodeProcess(h, (LPDWORD)status);
|
||||
|
||||
EnterCriticalSection(&pinfo_cs);
|
||||
|
||||
ppinfo = &pinfo;
|
||||
while (*ppinfo) {
|
||||
struct pinfo_t *info = *ppinfo;
|
||||
if (info->pid == pid) {
|
||||
CloseHandle(info->proc);
|
||||
*ppinfo = info->next;
|
||||
free(info);
|
||||
break;
|
||||
}
|
||||
ppinfo = &info->next;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&pinfo_cs);
|
||||
|
||||
CloseHandle(h);
|
||||
return pid;
|
||||
}
|
||||
CloseHandle(h);
|
||||
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
|
||||
#ifndef NO_MINGW_REPLACE_READDIR
|
||||
/* MinGW readdir implementation to avoid extra lstats for Git */
|
||||
struct mingw_DIR
|
||||
|
@ -140,13 +140,7 @@ static inline int mingw_unlink(const char *pathname)
|
||||
}
|
||||
#define unlink mingw_unlink
|
||||
|
||||
static inline pid_t waitpid(pid_t pid, int *status, unsigned options)
|
||||
{
|
||||
if (options == 0)
|
||||
return _cwait(status, pid, 0);
|
||||
errno = EINVAL;
|
||||
return -1;
|
||||
}
|
||||
pid_t waitpid(pid_t pid, int *status, unsigned options);
|
||||
|
||||
#ifndef NO_OPENSSL
|
||||
#include <openssl/ssl.h>
|
||||
@ -321,11 +315,13 @@ void free_environ(char **env);
|
||||
static int mingw_main(); \
|
||||
int main(int argc, const char **argv) \
|
||||
{ \
|
||||
extern CRITICAL_SECTION pinfo_cs; \
|
||||
_fmode = _O_BINARY; \
|
||||
_setmode(_fileno(stdin), _O_BINARY); \
|
||||
_setmode(_fileno(stdout), _O_BINARY); \
|
||||
_setmode(_fileno(stderr), _O_BINARY); \
|
||||
argv[0] = xstrdup(_pgmptr); \
|
||||
InitializeCriticalSection(&pinfo_cs); \
|
||||
return mingw_main(argc, argv); \
|
||||
} \
|
||||
static int mingw_main(c,v)
|
||||
|
Loading…
Reference in New Issue
Block a user