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:

committed by
Junio C Hamano

parent
bb34c5aabe
commit
52de4db579
@ -702,6 +702,14 @@ static int env_compare(const void *a, const void *b)
|
|||||||
return strcasecmp(*ea, *eb);
|
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,
|
static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
|
||||||
const char *dir,
|
const char *dir,
|
||||||
int prepend_cmd, int fhin, int fhout, int fherr)
|
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;
|
return -1;
|
||||||
}
|
}
|
||||||
CloseHandle(pi.hThread);
|
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,
|
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);
|
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
|
#ifndef NO_MINGW_REPLACE_READDIR
|
||||||
/* MinGW readdir implementation to avoid extra lstats for Git */
|
/* MinGW readdir implementation to avoid extra lstats for Git */
|
||||||
struct mingw_DIR
|
struct mingw_DIR
|
||||||
|
@ -140,13 +140,7 @@ static inline int mingw_unlink(const char *pathname)
|
|||||||
}
|
}
|
||||||
#define unlink mingw_unlink
|
#define unlink mingw_unlink
|
||||||
|
|
||||||
static inline pid_t waitpid(pid_t pid, int *status, unsigned options)
|
pid_t waitpid(pid_t pid, int *status, unsigned options);
|
||||||
{
|
|
||||||
if (options == 0)
|
|
||||||
return _cwait(status, pid, 0);
|
|
||||||
errno = EINVAL;
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
#ifndef NO_OPENSSL
|
#ifndef NO_OPENSSL
|
||||||
#include <openssl/ssl.h>
|
#include <openssl/ssl.h>
|
||||||
@ -321,11 +315,13 @@ void free_environ(char **env);
|
|||||||
static int mingw_main(); \
|
static int mingw_main(); \
|
||||||
int main(int argc, const char **argv) \
|
int main(int argc, const char **argv) \
|
||||||
{ \
|
{ \
|
||||||
|
extern CRITICAL_SECTION pinfo_cs; \
|
||||||
_fmode = _O_BINARY; \
|
_fmode = _O_BINARY; \
|
||||||
_setmode(_fileno(stdin), _O_BINARY); \
|
_setmode(_fileno(stdin), _O_BINARY); \
|
||||||
_setmode(_fileno(stdout), _O_BINARY); \
|
_setmode(_fileno(stdout), _O_BINARY); \
|
||||||
_setmode(_fileno(stderr), _O_BINARY); \
|
_setmode(_fileno(stderr), _O_BINARY); \
|
||||||
argv[0] = xstrdup(_pgmptr); \
|
argv[0] = xstrdup(_pgmptr); \
|
||||||
|
InitializeCriticalSection(&pinfo_cs); \
|
||||||
return mingw_main(argc, argv); \
|
return mingw_main(argc, argv); \
|
||||||
} \
|
} \
|
||||||
static int mingw_main(c,v)
|
static int mingw_main(c,v)
|
||||||
|
Reference in New Issue
Block a user