@matheusbsbs / matheus-bagliano / commits / 52de4db579
Fork 0

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>

Erik Faye-Lund committed Nov 4, 2010 at 02:35 UTC 52de4db57977175c5ad1d6c3922e772d6de08496
2 files changed +75 -8
compat/mingw.c
+72 -1
@@ -702,6 +702,14 @@ static int env_compare(const void *a, const void *b)
702 return strcasecmp(*ea, *eb);
703 }
704
705 +struct pinfo_t {
706 + struct pinfo_t *next;
707 + pid_t pid;
708 + HANDLE proc;
709 +} pinfo_t;
710 +struct pinfo_t *pinfo = NULL;
711 +CRITICAL_SECTION pinfo_cs;
712 +
713 static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,
714 const char *dir,
715 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,
802 return -1;
803 }
804 CloseHandle(pi.hThread);
797 - return (pid_t)pi.hProcess;
805 +
806 + /*
807 + * The process ID is the human-readable identifier of the process
808 + * that we want to present in log and error messages. The handle
809 + * is not useful for this purpose. But we cannot close it, either,
810 + * because it is not possible to turn a process ID into a process
811 + * handle after the process terminated.
812 + * Keep the handle in a list for waitpid.
813 + */
814 + EnterCriticalSection(&pinfo_cs);
815 + {
816 + struct pinfo_t *info = xmalloc(sizeof(struct pinfo_t));
817 + info->pid = pi.dwProcessId;
818 + info->proc = pi.hProcess;
819 + info->next = pinfo;
820 + pinfo = info;
821 + }
822 + LeaveCriticalSection(&pinfo_cs);
823 +
824 + return (pid_t)pi.dwProcessId;
825 }
826
827 static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,
@@ -1518,6 +1545,50 @@ char *getpass(const char *prompt)
1545 return strbuf_detach(&buf, NULL);
1546 }
1547
1548 +pid_t waitpid(pid_t pid, int *status, unsigned options)
1549 +{
1550 + HANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,
1551 + FALSE, pid);
1552 + if (!h) {
1553 + errno = ECHILD;
1554 + return -1;
1555 + }
1556 +
1557 + if (options == 0) {
1558 + struct pinfo_t **ppinfo;
1559 + if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {
1560 + CloseHandle(h);
1561 + return 0;
1562 + }
1563 +
1564 + if (status)
1565 + GetExitCodeProcess(h, (LPDWORD)status);
1566 +
1567 + EnterCriticalSection(&pinfo_cs);
1568 +
1569 + ppinfo = &pinfo;
1570 + while (*ppinfo) {
1571 + struct pinfo_t *info = *ppinfo;
1572 + if (info->pid == pid) {
1573 + CloseHandle(info->proc);
1574 + *ppinfo = info->next;
1575 + free(info);
1576 + break;
1577 + }
1578 + ppinfo = &info->next;
1579 + }
1580 +
1581 + LeaveCriticalSection(&pinfo_cs);
1582 +
1583 + CloseHandle(h);
1584 + return pid;
1585 + }
1586 + CloseHandle(h);
1587 +
1588 + errno = EINVAL;
1589 + return -1;
1590 +}
1591 +
1592 #ifndef NO_MINGW_REPLACE_READDIR
1593 /* MinGW readdir implementation to avoid extra lstats for Git */
1594 struct mingw_DIR
compat/mingw.h
+3 -7
@@ -140,13 +140,7 @@ static inline int mingw_unlink(const char *pathname)
140 }
141 #define unlink mingw_unlink
142
143 -static inline pid_t waitpid(pid_t pid, int *status, unsigned options)
144 -{
145 - if (options == 0)
146 - return _cwait(status, pid, 0);
147 - errno = EINVAL;
148 - return -1;
149 -}
143 +pid_t waitpid(pid_t pid, int *status, unsigned options);
144
145 #ifndef NO_OPENSSL
146 #include <openssl/ssl.h>
@@ -321,11 +315,13 @@ void free_environ(char **env);
315 static int mingw_main(); \
316 int main(int argc, const char **argv) \
317 { \
318 + extern CRITICAL_SECTION pinfo_cs; \
319 _fmode = _O_BINARY; \
320 _setmode(_fileno(stdin), _O_BINARY); \
321 _setmode(_fileno(stdout), _O_BINARY); \
322 _setmode(_fileno(stderr), _O_BINARY); \
323 argv[0] = xstrdup(_pgmptr); \
324 + InitializeCriticalSection(&pinfo_cs); \
325 return mingw_main(argc, argv); \
326 } \
327 static int mingw_main(c,v)