Skip to content

Commit

Permalink
mingw: use real pid
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Erik Faye-Lund authored and Junio C Hamano committed Nov 4, 2010
1 parent bb34c5a commit 52de4db
Show file tree
Hide file tree
Showing 2 changed files with 75 additions and 8 deletions.
73 changes: 72 additions & 1 deletion compat/mingw.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
10 changes: 3 additions & 7 deletions compat/mingw.h
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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)
Expand Down

0 comments on commit 52de4db

Please sign in to comment.