{"thread":{"id":"22235","subject":"[PATCH v2 00/14] daemon-win32","startedAt":"2010-01-15T21:30:19Z","lastAt":"2010-01-19T19:23:32Z","messageCount":49,"participants":["Erik Faye-Lund","Johannes Sixt","Janos Laube","Andreas Schwab"],"isPatch":true,"patchVersion":2,"patchTotal":14},"messages":[{"id":"131770","messageId":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":null,"subject":"[PATCH v2 00/14] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:19Z","receivedAt":"2010-01-15T21:30:19Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Here's the long overdue v2 of my daemon-win32 attempt. A lot\nhas happened since v1. Most importantly, I abandoned using\nthe async API to replace fork(), and went for explicitly\nspawning child process that handle the connection.\n\nThe patches are on top of the current version of Junio's\nmaster-branch.\n\nWhen talking about patch numbers here, I'm referring to the numbers\nfrom the previous round.\n\nPatch 1 has been adjusted to work on top of Martin's ipv6 patches.\n\nPatch 2 has been dropped, because it was made obsolete by the\nchanges to patch 3.\n\nPatch 3 has been simplified as suggested by Hannes. The problem with\nreporting IPv6 addresses should still be there in theory, but I\nhaven't been able to trigger it. I'm having a feeling that it's better\nto do a case-by-case patch of the code that reports for this one.\n\nPatch 4 and 5 are unchanged.\n\nPatch 6 and 7 were dropped, in favour of a new approach.\n\nPatch 8 has been updated as suggested.\n\nPatch 9 has been rewritten to spawn a separate child process that\nserves the client.\n\nPatch 10 is unchanged\n\nPatch 11 has been updated as suggested.\n\nIn addition, I've added a patch that add some needed support in\nour waitpid()-emulation, a (very limited) kill()-emulation, a patch\nthat uses real PIDs on Windows (instead of process-local kernel-handles),\na patch that changes the code to use select() instead of poll() to wait\nfor socket-action (due to our limited poll-emulation). And there's a\npatch that makes sure connections are reported from the root-process.\n\nIn addition, I've attached an updated version of the getaddrinfo()-fix\nthat Martin sent me privately. I removed Hannes sign-off (as requested by\nMartin, due to the update)\n\nThe branch can also be found here:\nhttp://repo.or.cz/w/git/kusma.git daemon-win32-v2\n\nPuuuh, I hope I didn't miss anything important.\n\n\nErik Faye-Lund (10):\n  inet_ntop: fix a couple of old-style decls\n  mingw: support waitpid with pid > 0 and WNOHANG\n  mingw: use real pid\n  mingw: add kill emulation\n  daemon: use explicit file descriptor\n  daemon: use run-command api for async serving\n  daemon: use full buffered mode for stderr\n  mingw: compile git-daemon\n  daemon: use select() instead of poll()\n  daemon: report connection from root-process\n\nMartin Storsjö (1):\n  Improve the mingw getaddrinfo stub to handle more use cases\n\nMike Pape (3):\n  mingw: add network-wrappers for daemon\n  mingw: implement syslog\n  compat: add inet_pton and inet_ntop prototypes\n\n Makefile           |   10 +-\n compat/inet_ntop.c |   22 ++----\n compat/inet_pton.c |    8 +-\n compat/mingw.c     |  141 +++++++++++++++++++++++++++++--\n compat/mingw.h     |   80 +++++++++++++++++-\n daemon.c           |  236 ++++++++++++++++++++++++++++------------------------\n git-compat-util.h  |    9 ++\n 7 files changed, 361 insertions(+), 145 deletions(-)\n"},{"id":"131771","messageId":"1263591033-4992-2-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 01/14] mingw: add network-wrappers for daemon","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:20Z","receivedAt":"2010-01-15T21:30:20Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"From: Mike Pape <dotzenlabs@gmail.com>\n\ngit-daemon requires some socket-functionality that is not yet\nsupported in the Windows-port. This patch adds said functionality,\nand makes sure WSAStartup gets called by socket(), since it is the\nfirst network-call in git-daemon. In addition, a check is added to\nprevent WSAStartup (and WSACleanup, though atexit) from being\ncalled more than once, since git-daemon calls both socket() and\ngethostbyname().\n\nSigned-off-by: Mike Pape <dotzenlabs@gmail.com>\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c |   43 ++++++++++++++++++++++++++++++++++++++++++-\n compat/mingw.h |   16 ++++++++++++++++\n 2 files changed, 58 insertions(+), 1 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 0d73f15..42ef9e2 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1095,7 +1095,10 @@ int mingw_getnameinfo(const struct sockaddr *sa, socklen_t salen,\n int mingw_socket(int domain, int type, int protocol)\n {\n \tint sockfd;\n-\tSOCKET s = WSASocket(domain, type, protocol, NULL, 0, 0);\n+\tSOCKET s;\n+\n+\tensure_socket_initialization();\n+\ts = WSASocket(domain, type, protocol, NULL, 0, 0);\n \tif (s == INVALID_SOCKET) {\n \t\t/*\n \t\t * WSAGetLastError() values are regular BSD error codes\n@@ -1125,6 +1128,44 @@ int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz)\n \treturn connect(s, sa, sz);\n }\n \n+#undef bind\n+int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz)\n+{\n+\tSOCKET s = (SOCKET)_get_osfhandle(sockfd);\n+\treturn bind(s, sa, sz);\n+}\n+\n+#undef setsockopt\n+int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen)\n+{\n+\tSOCKET s = (SOCKET)_get_osfhandle(sockfd);\n+\treturn setsockopt(s, lvl, optname, (const char*)optval, optlen);\n+}\n+\n+#undef listen\n+int mingw_listen(int sockfd, int backlog)\n+{\n+\tSOCKET s = (SOCKET)_get_osfhandle(sockfd);\n+\treturn listen(s, backlog);\n+}\n+\n+#undef accept\n+int mingw_accept(int sockfd1, struct sockaddr *sa, socklen_t *sz)\n+{\n+\tint sockfd2;\n+\n+\tSOCKET s1 = (SOCKET)_get_osfhandle(sockfd1);\n+\tSOCKET s2 = accept(s1, sa, sz);\n+\n+\t/* convert into a file descriptor */\n+\tif ((sockfd2 = _open_osfhandle(s2, O_RDWR|O_BINARY)) < 0) {\n+\t\tclosesocket(s2);\n+\t\treturn error(\"unable to make a socket file descriptor: %s\",\n+\t\t\tstrerror(errno));\n+\t}\n+\treturn sockfd2;\n+}\n+\n #undef rename\n int mingw_rename(const char *pold, const char *pnew)\n {\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex b3d299f..07513bb 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -6,6 +6,7 @@\n  */\n \n typedef int pid_t;\n+typedef int socklen_t;\n #define hstrerror strerror\n \n #define S_IFLNK    0120000 /* Symbolic link */\n@@ -34,6 +35,9 @@ typedef int pid_t;\n #define F_SETFD 2\n #define FD_CLOEXEC 0x1\n \n+#define EAFNOSUPPORT WSAEAFNOSUPPORT\n+#define ECONNABORTED WSAECONNABORTED\n+\n struct passwd {\n \tchar *pw_name;\n \tchar *pw_gecos;\n@@ -197,6 +201,18 @@ int mingw_socket(int domain, int type, int protocol);\n int mingw_connect(int sockfd, struct sockaddr *sa, size_t sz);\n #define connect mingw_connect\n \n+int mingw_bind(int sockfd, struct sockaddr *sa, size_t sz);\n+#define bind mingw_bind\n+\n+int mingw_setsockopt(int sockfd, int lvl, int optname, void *optval, int optlen);\n+#define setsockopt mingw_setsockopt\n+\n+int mingw_listen(int sockfd, int backlog);\n+#define listen mingw_listen\n+\n+int mingw_accept(int sockfd, struct sockaddr *sa, socklen_t *sz);\n+#define accept mingw_accept\n+\n int mingw_rename(const char*, const char*);\n #define rename mingw_rename\n \n-- \n1.6.6.211.g26720\n"},{"id":"131774","messageId":"1263591033-4992-3-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 02/14] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:21Z","receivedAt":"2010-01-15T21:30:21Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"From: Mike Pape <dotzenlabs@gmail.com>\n\nSyslog does not usually exist on Windows, so we implement our own\nusing Window's ReportEvent mechanism.\n\nSigned-off-by: Mike Pape <dotzenlabs@gmail.com>\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c    |   49 +++++++++++++++++++++++++++++++++++++++++++++++++\n compat/mingw.h    |   15 +++++++++++++++\n daemon.c          |    2 --\n git-compat-util.h |    1 +\n 4 files changed, 65 insertions(+), 2 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 42ef9e2..54be905 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1351,6 +1351,55 @@ int sigaction(int sig, struct sigaction *in, struct sigaction *out)\n \treturn 0;\n }\n \n+static HANDLE ms_eventlog;\n+\n+void openlog(const char *ident, int logopt, int facility)\n+{\n+\tif (ms_eventlog)\n+\t\treturn;\n+\tms_eventlog = RegisterEventSourceA(NULL, ident);\n+}\n+\n+void syslog(int priority, const char *fmt, const char *arg)\n+{\n+\tWORD logtype;\n+\n+\tif (strcmp(fmt, \"%s\")) {\n+\t\twarning(\"format string of syslog() not implemented\");\n+\t\treturn;\n+\t}\n+\n+\tswitch (priority) {\n+\t\tcase LOG_EMERG:\n+\t\tcase LOG_ALERT:\n+\t\tcase LOG_CRIT:\n+\t\tcase LOG_ERR:\n+\t\t\tlogtype = EVENTLOG_ERROR_TYPE;\n+\t\t\tbreak;\n+\n+\t\tcase LOG_WARNING:\n+\t\t\tlogtype = EVENTLOG_WARNING_TYPE;\n+\t\t\tbreak;\n+\n+\t\tcase LOG_NOTICE:\n+\t\tcase LOG_INFO:\n+\t\tcase LOG_DEBUG:\n+\t\tdefault:\n+\t\t\tlogtype = EVENTLOG_INFORMATION_TYPE;\n+\t\t\tbreak;\n+\t}\n+\n+\tReportEventA(ms_eventlog,\n+\t    logtype,\n+\t    0,\n+\t    0,\n+\t    NULL,\n+\t    1,\n+\t    0,\n+\t    (const char **)&arg,\n+\t    NULL);\n+}\n+\n #undef signal\n sig_handler_t mingw_signal(int sig, sig_handler_t handler)\n {\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 07513bb..d934e56 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -38,6 +38,19 @@ typedef int socklen_t;\n #define EAFNOSUPPORT WSAEAFNOSUPPORT\n #define ECONNABORTED WSAECONNABORTED\n \n+#define LOG_PID     0x01\n+\n+#define LOG_EMERG   0\n+#define LOG_ALERT   1\n+#define LOG_CRIT    2\n+#define LOG_ERR     3\n+#define LOG_WARNING 4\n+#define LOG_NOTICE  5\n+#define LOG_INFO    6\n+#define LOG_DEBUG   7\n+\n+#define LOG_DAEMON  (3<<3)\n+\n struct passwd {\n \tchar *pw_name;\n \tchar *pw_gecos;\n@@ -166,6 +179,8 @@ struct passwd *getpwuid(int uid);\n int setitimer(int type, struct itimerval *in, struct itimerval *out);\n int sigaction(int sig, struct sigaction *in, struct sigaction *out);\n int link(const char *oldpath, const char *newpath);\n+void openlog(const char *ident, int logopt, int facility);\n+void syslog(int priority, const char *fmt, const char *arg);\n \n /*\n  * replacements of existing functions\ndiff --git a/daemon.c b/daemon.c\nindex 918e560..79ba1aa 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -4,8 +4,6 @@\n #include \"run-command.h\"\n #include \"strbuf.h\"\n \n-#include <syslog.h>\n-\n #ifndef HOST_NAME_MAX\n #define HOST_NAME_MAX 256\n #endif\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 5c59687..30e6240 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -105,6 +105,7 @@\n #include <netdb.h>\n #include <pwd.h>\n #include <inttypes.h>\n+#include <syslog.h>\n #if defined(__CYGWIN__)\n #undef _XOPEN_SOURCE\n #include <grp.h>\n-- \n1.6.6.211.g26720\n"},{"id":"131775","messageId":"1263591033-4992-4-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 03/14] compat: add inet_pton and inet_ntop prototypes","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:22Z","receivedAt":"2010-01-15T21:30:22Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"From: Mike Pape <dotzenlabs@gmail.com>\n\nWindows doesn't have inet_pton and inet_ntop, so\nadd prototypes in git-compat-util.h for them.\n\nAt the same time include git-compat-util.h in\nthe sources for these functions, so they use the\nnetwork-wrappers from there on Windows.\n\nSigned-off-by: Mike Pape <dotzenlabs@gmail.com>\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n Makefile           |    2 ++\n compat/inet_ntop.c |    6 +++---\n compat/inet_pton.c |    8 +++++---\n git-compat-util.h  |    8 ++++++++\n 4 files changed, 18 insertions(+), 6 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex ebaa75c..d81b392 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1289,9 +1289,11 @@ endif\n endif\n ifdef NO_INET_NTOP\n \tLIB_OBJS += compat/inet_ntop.o\n+\tBASIC_CFLAGS += -DNO_INET_NTOP\n endif\n ifdef NO_INET_PTON\n \tLIB_OBJS += compat/inet_pton.o\n+\tBASIC_CFLAGS += -DNO_INET_PTON\n endif\n \n ifdef NO_ICONV\ndiff --git a/compat/inet_ntop.c b/compat/inet_ntop.c\nindex f444982..e5b46a0 100644\n--- a/compat/inet_ntop.c\n+++ b/compat/inet_ntop.c\n@@ -17,9 +17,9 @@\n \n #include <errno.h>\n #include <sys/types.h>\n-#include <sys/socket.h>\n-#include <netinet/in.h>\n-#include <arpa/inet.h>\n+\n+#include \"../git-compat-util.h\"\n+\n #include <stdio.h>\n #include <string.h>\n \ndiff --git a/compat/inet_pton.c b/compat/inet_pton.c\nindex 4078fc0..2ec995e 100644\n--- a/compat/inet_pton.c\n+++ b/compat/inet_pton.c\n@@ -17,9 +17,9 @@\n \n #include <errno.h>\n #include <sys/types.h>\n-#include <sys/socket.h>\n-#include <netinet/in.h>\n-#include <arpa/inet.h>\n+\n+#include \"../git-compat-util.h\"\n+\n #include <stdio.h>\n #include <string.h>\n \n@@ -41,7 +41,9 @@\n  */\n \n static int inet_pton4(const char *src, unsigned char *dst);\n+#ifndef NO_IPV6\n static int inet_pton6(const char *src, unsigned char *dst);\n+#endif\n \n /* int\n  * inet_pton4(src, dst)\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 30e6240..937fb1b 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -341,6 +341,14 @@ static inline char *gitstrchrnul(const char *s, int c)\n }\n #endif\n \n+#ifdef NO_INET_PTON\n+int inet_pton(int af, const char *src, void *dst);\n+#endif\n+\n+#ifdef NO_INET_NTOP\n+const char *inet_ntop(int af, const void *src, char *dst, size_t size);\n+#endif\n+\n extern void release_pack_memory(size_t, int);\n \n extern char *xstrdup(const char *str);\n-- \n1.6.6.211.g26720\n"},{"id":"131772","messageId":"1263591033-4992-5-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 04/14] inet_ntop: fix a couple of old-style decls","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:23Z","receivedAt":"2010-01-15T21:30:23Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/inet_ntop.c |   16 +++-------------\n 1 files changed, 3 insertions(+), 13 deletions(-)\n\ndiff --git a/compat/inet_ntop.c b/compat/inet_ntop.c\nindex e5b46a0..ea249c6 100644\n--- a/compat/inet_ntop.c\n+++ b/compat/inet_ntop.c\n@@ -50,10 +50,7 @@\n  *\tPaul Vixie, 1996.\n  */\n static const char *\n-inet_ntop4(src, dst, size)\n-\tconst u_char *src;\n-\tchar *dst;\n-\tsize_t size;\n+inet_ntop4(const u_char *src, char *dst, size_t size)\n {\n \tstatic const char fmt[] = \"%u.%u.%u.%u\";\n \tchar tmp[sizeof \"255.255.255.255\"];\n@@ -78,10 +75,7 @@ inet_ntop4(src, dst, size)\n  *\tPaul Vixie, 1996.\n  */\n static const char *\n-inet_ntop6(src, dst, size)\n-\tconst u_char *src;\n-\tchar *dst;\n-\tsize_t size;\n+inet_ntop6(const u_char *src, char *dst, size_t size)\n {\n \t/*\n \t * Note that int32_t and int16_t need only be \"at least\" large enough\n@@ -178,11 +172,7 @@ inet_ntop6(src, dst, size)\n  *\tPaul Vixie, 1996.\n  */\n const char *\n-inet_ntop(af, src, dst, size)\n-\tint af;\n-\tconst void *src;\n-\tchar *dst;\n-\tsize_t size;\n+inet_ntop(int af, const void *src, char *dst, size_t size)\n {\n \tswitch (af) {\n \tcase AF_INET:\n-- \n1.6.6.211.g26720\n"},{"id":"131773","messageId":"1263591033-4992-6-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 05/14] mingw: support waitpid with pid > 0 and WNOHANG","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:24Z","receivedAt":"2010-01-15T21:30:24Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Signed-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.h |    7 +++++++\n 1 files changed, 7 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex d934e56..3005472 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -134,8 +134,15 @@ static inline int mingw_unlink(const char *pathname)\n }\n #define unlink mingw_unlink\n \n+#define WNOHANG 1\n static inline int waitpid(pid_t pid, int *status, unsigned options)\n {\n+\tif (pid > 0 && options & WNOHANG) {\n+\t\tif (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n+\t\t\treturn 0;\n+\t\toptions &= ~WNOHANG;\n+\t}\n+\n \tif (options == 0)\n \t\treturn _cwait(status, pid, 0);\n \terrno = EINVAL;\n-- \n1.6.6.211.g26720\n"},{"id":"131776","messageId":"1263591033-4992-7-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 06/14] mingw: use real pid","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:25Z","receivedAt":"2010-01-15T21:30:25Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"The Windows port so far used process handles as PID. However,\nthis does not work consistently with getpid.\n\nChange the code to use the real PID, and use OpenProcess to\nget a process-handle.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c |    2 +-\n compat/mingw.h |   35 +++++++++++++++++++++++++++++++----\n 2 files changed, 32 insertions(+), 5 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 54be905..ce4f829 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -729,7 +729,7 @@ static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,\n \t\treturn -1;\n \t}\n \tCloseHandle(pi.hThread);\n-\treturn (pid_t)pi.hProcess;\n+\treturn (pid_t)pi.dwProcessId;\n }\n \n pid_t mingw_spawnvpe(const char *cmd, const char **argv, char **env)\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 3005472..ff4a76b 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -137,14 +137,41 @@ static inline int mingw_unlink(const char *pathname)\n #define WNOHANG 1\n static inline int waitpid(pid_t pid, int *status, unsigned options)\n {\n-\tif (pid > 0 && options & WNOHANG) {\n-\t\tif (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n+\tHANDLE h;\n+\n+\tif (pid <= 0) {\n+\t\terrno = EINVAL;\n+\t\treturn -1;\n+\t}\n+\n+\th = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION, FALSE, pid);\n+\tif (!h) {\n+\t\terrno = ECHILD;\n+\t\treturn -1;\n+\t}\n+\n+\tif (options & WNOHANG) {\n+\t\tif (WaitForSingleObject(h, 0) != WAIT_OBJECT_0) {\n+\t\t\tCloseHandle(h);\n \t\t\treturn 0;\n+\t\t}\n \t\toptions &= ~WNOHANG;\n \t}\n \n-\tif (options == 0)\n-\t\treturn _cwait(status, pid, 0);\n+\tif (options == 0) {\n+\t\tif (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {\n+\t\t\tCloseHandle(h);\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t\tif (status)\n+\t\t\tGetExitCodeProcess(h, (LPDWORD)status);\n+\n+\t\tCloseHandle(h);\n+\t\treturn pid;\n+\t}\n+\tCloseHandle(h);\n+\n \terrno = EINVAL;\n \treturn -1;\n }\n-- \n1.6.6.211.g26720\n"},{"id":"131777","messageId":"1263591033-4992-8-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 07/14] mingw: add kill emulation","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:26Z","receivedAt":"2010-01-15T21:30:26Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"This is a quite limited kill-emulation; it can only handle\nSIGTERM on positive pids. However, it's enough for git-daemon.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c |   19 +++++++++++++++++++\n compat/mingw.h |    3 +++\n 2 files changed, 22 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex ce4f829..89b9b89 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -829,6 +829,25 @@ void mingw_execvp(const char *cmd, char *const *argv)\n \tfree_path_split(path);\n }\n \n+int mingw_kill(pid_t pid, int sig)\n+{\n+\tif (pid > 0 && sig == SIGTERM) {\n+\t\tHANDLE h = OpenProcess(PROCESS_TERMINATE, FALSE, pid);\n+\n+\t\tif (TerminateProcess(h, -1)) {\n+\t\t\tCloseHandle(h);\n+\t\t\treturn 0;\n+\t\t}\n+\n+\t\tCloseHandle(h);\n+\t\terrno = err_win_to_posix(GetLastError());\n+\t\treturn -1;\n+\t}\n+\n+\terrno = EINVAL;\n+\treturn -1;\n+}\n+\n static char **copy_environ(void)\n {\n \tchar **env;\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex ff4a76b..e72c2ee 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -176,6 +176,9 @@ static inline int waitpid(pid_t pid, int *status, unsigned options)\n \treturn -1;\n }\n \n+#define kill mingw_kill\n+int mingw_kill(pid_t pid, int sig);\n+\n #ifndef NO_OPENSSL\n #include <openssl/ssl.h>\n static inline int mingw_SSL_set_fd(SSL *ssl, int fd)\n-- \n1.6.6.211.g26720\n"},{"id":"131778","messageId":"1263591033-4992-9-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 08/14] daemon: use explicit file descriptor","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:27Z","receivedAt":"2010-01-15T21:30:27Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"This patch adds support to specify an explicit file\ndescriotor for communication with the client, instead\nof using stdin/stdout.\n\nThis will be useful for the Windows port, because it\nwill use threads instead of fork() to serve multiple\nclients, making it impossible to reuse stdin/stdout.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n daemon.c |   43 +++++++++++++++++++++----------------------\n 1 files changed, 21 insertions(+), 22 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 79ba1aa..b42792f 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -218,7 +218,7 @@ static char *path_ok(char *directory)\n \treturn NULL;\t\t/* Fallthrough. Deny by default */\n }\n \n-typedef int (*daemon_service_fn)(void);\n+typedef int (*daemon_service_fn)(int [2]);\n struct daemon_service {\n \tconst char *name;\n \tconst char *config_name;\n@@ -242,7 +242,7 @@ static int git_daemon_config(const char *var, const char *value, void *cb)\n \treturn 0;\n }\n \n-static int run_service(char *dir, struct daemon_service *service)\n+static int run_service(int fd[2], char *dir, struct daemon_service *service)\n {\n \tconst char *path;\n \tint enabled = service->enabled;\n@@ -295,7 +295,7 @@ static int run_service(char *dir, struct daemon_service *service)\n \t */\n \tsignal(SIGTERM, SIG_IGN);\n \n-\treturn service->fn();\n+\treturn service->fn(fd);\n }\n \n static void copy_to_log(int fd)\n@@ -319,7 +319,7 @@ static void copy_to_log(int fd)\n \tfclose(fp);\n }\n \n-static int run_service_command(const char **argv)\n+static int run_service_command(int fd[2], const char **argv)\n {\n \tstruct child_process cld;\n \n@@ -327,37 +327,36 @@ static int run_service_command(const char **argv)\n \tcld.argv = argv;\n \tcld.git_cmd = 1;\n \tcld.err = -1;\n+\tcld.in = fd[0];\n+\tcld.out = fd[1];\n \tif (start_command(&cld))\n \t\treturn -1;\n \n-\tclose(0);\n-\tclose(1);\n-\n \tcopy_to_log(cld.err);\n \n \treturn finish_command(&cld);\n }\n \n-static int upload_pack(void)\n+static int upload_pack(int fd[2])\n {\n \t/* Timeout as string */\n \tchar timeout_buf[64];\n \tconst char *argv[] = { \"upload-pack\", \"--strict\", timeout_buf, \".\", NULL };\n \n \tsnprintf(timeout_buf, sizeof timeout_buf, \"--timeout=%u\", timeout);\n-\treturn run_service_command(argv);\n+\treturn run_service_command(fd, argv);\n }\n \n-static int upload_archive(void)\n+static int upload_archive(int fd[2])\n {\n \tstatic const char *argv[] = { \"upload-archive\", \".\", NULL };\n-\treturn run_service_command(argv);\n+\treturn run_service_command(fd, argv);\n }\n \n-static int receive_pack(void)\n+static int receive_pack(int fd[2])\n {\n \tstatic const char *argv[] = { \"receive-pack\", \".\", NULL };\n-\treturn run_service_command(argv);\n+\treturn run_service_command(fd, argv);\n }\n \n static struct daemon_service daemon_service[] = {\n@@ -487,7 +486,7 @@ static void parse_host_arg(char *extra_args, int buflen)\n }\n \n \n-static int execute(struct sockaddr *addr)\n+static int execute(int fd[2], struct sockaddr *addr)\n {\n \tstatic char line[1000];\n \tint pktlen, len, i;\n@@ -520,7 +519,7 @@ static int execute(struct sockaddr *addr)\n \t}\n \n \talarm(init_timeout ? init_timeout : timeout);\n-\tpktlen = packet_read_line(0, line, sizeof(line));\n+\tpktlen = packet_read_line(fd[0], line, sizeof(line));\n \talarm(0);\n \n \tlen = strlen(line);\n@@ -552,7 +551,7 @@ static int execute(struct sockaddr *addr)\n \t\t\t * Note: The directory here is probably context sensitive,\n \t\t\t * and might depend on the actual service being performed.\n \t\t\t */\n-\t\t\treturn run_service(line + namelen + 5, s);\n+\t\t\treturn run_service(fd, line + namelen + 5, s);\n \t\t}\n \t}\n \n@@ -652,6 +651,7 @@ static void check_dead_children(void)\n \n static void handle(int incoming, struct sockaddr *addr, int addrlen)\n {\n+\tint fd[2];\n \tpid_t pid;\n \n \tif (max_connections && live_children >= max_connections) {\n@@ -676,11 +676,9 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)\n \t\treturn;\n \t}\n \n-\tdup2(incoming, 0);\n-\tdup2(incoming, 1);\n-\tclose(incoming);\n-\n-\texit(execute(addr));\n+\tfd[0] = incoming;\n+\tfd[1] = dup(incoming);\n+\texit(execute(fd, addr));\n }\n \n static void child_handler(int signo)\n@@ -1107,6 +1105,7 @@ int main(int argc, char **argv)\n \t\t    base_path);\n \n \tif (inetd_mode) {\n+\t\tint fd[2] = { 0, 1 };\n \t\tstruct sockaddr_storage ss;\n \t\tstruct sockaddr *peer = (struct sockaddr *)&ss;\n \t\tsocklen_t slen = sizeof(ss);\n@@ -1117,7 +1116,7 @@ int main(int argc, char **argv)\n \t\tif (getpeername(0, peer, &slen))\n \t\t\tpeer = NULL;\n \n-\t\treturn execute(peer);\n+\t\treturn execute(fd, peer);\n \t}\n \n \tif (detach) {\n-- \n1.6.6.211.g26720\n"},{"id":"131779","messageId":"1263591033-4992-10-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 09/14] daemon: use run-command api for async serving","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:28Z","receivedAt":"2010-01-15T21:30:28Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"fork() is only available on POSIX, so to support git-daemon\non Windows we have to use something else. Conveniently\nenough, we have an API for async operation already.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n daemon.c |   87 +++++++++++++++++++++++++++++++------------------------------\n 1 files changed, 44 insertions(+), 43 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex b42792f..2d63cbc 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -583,17 +583,17 @@ static unsigned int live_children;\n \n static struct child {\n \tstruct child *next;\n-\tpid_t pid;\n+\tstruct child_process cld;\n \tstruct sockaddr_storage address;\n } *firstborn;\n \n-static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)\n+static void add_child(struct child_process *cld, struct sockaddr *addr, int addrlen)\n {\n \tstruct child *newborn, **cradle;\n \n \tnewborn = xcalloc(1, sizeof(*newborn));\n \tlive_children++;\n-\tnewborn->pid = pid;\n+\tmemcpy(&newborn->cld, cld, sizeof(*cld));\n \tmemcpy(&newborn->address, addr, addrlen);\n \tfor (cradle = &firstborn; *cradle; cradle = &(*cradle)->next)\n \t\tif (!addrcmp(&(*cradle)->address, &newborn->address))\n@@ -602,19 +602,6 @@ static void add_child(pid_t pid, struct sockaddr *addr, int addrlen)\n \t*cradle = newborn;\n }\n \n-static void remove_child(pid_t pid)\n-{\n-\tstruct child **cradle, *blanket;\n-\n-\tfor (cradle = &firstborn; (blanket = *cradle); cradle = &blanket->next)\n-\t\tif (blanket->pid == pid) {\n-\t\t\t*cradle = blanket->next;\n-\t\t\tlive_children--;\n-\t\t\tfree(blanket);\n-\t\t\tbreak;\n-\t\t}\n-}\n-\n /*\n  * This gets called if the number of connections grows\n  * past \"max_connections\".\n@@ -623,14 +610,14 @@ static void remove_child(pid_t pid)\n  */\n static void kill_some_child(void)\n {\n-\tconst struct child *blanket, *next;\n+\tstruct child *blanket, *next;\n \n \tif (!(blanket = firstborn))\n \t\treturn;\n \n \tfor (; (next = blanket->next); blanket = next)\n \t\tif (!addrcmp(&blanket->address, &next->address)) {\n-\t\t\tkill(blanket->pid, SIGTERM);\n+\t\t\tkill(blanket->cld.pid, SIGTERM);\n \t\t\tbreak;\n \t\t}\n }\n@@ -640,19 +627,26 @@ static void check_dead_children(void)\n \tint status;\n \tpid_t pid;\n \n-\twhile ((pid = waitpid(-1, &status, WNOHANG)) > 0) {\n-\t\tconst char *dead = \"\";\n-\t\tremove_child(pid);\n-\t\tif (!WIFEXITED(status) || (WEXITSTATUS(status) > 0))\n-\t\t\tdead = \" (with error)\";\n-\t\tloginfo(\"[%\"PRIuMAX\"] Disconnected%s\", (uintmax_t)pid, dead);\n-\t}\n+\tstruct child **cradle, *blanket;\n+\tfor (cradle = &firstborn; (blanket = *cradle);)\n+\t\tif ((pid = waitpid(blanket->cld.pid, &status, WNOHANG)) > 1) {\n+\t\t\tconst char *dead = \"\";\n+\t\t\tif (status)\n+\t\t\t\tdead = \" (with error)\";\n+\t\t\tloginfo(\"[%\"PRIuMAX\"] Disconnected%s\", (uintmax_t)pid, dead);\n+\n+\t\t\t/* remove the child */\n+\t\t\t*cradle = blanket->next;\n+\t\t\tlive_children--;\n+\t\t\tfree(blanket);\n+\t\t} else\n+\t\t\tcradle = &blanket->next;\n }\n \n+char **cld_argv;\n static void handle(int incoming, struct sockaddr *addr, int addrlen)\n {\n-\tint fd[2];\n-\tpid_t pid;\n+\tstruct child_process cld = { 0 };\n \n \tif (max_connections && live_children >= max_connections) {\n \t\tkill_some_child();\n@@ -665,20 +659,15 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)\n \t\t}\n \t}\n \n-\tif ((pid = fork())) {\n-\t\tclose(incoming);\n-\t\tif (pid < 0) {\n-\t\t\tlogerror(\"Couldn't fork %s\", strerror(errno));\n-\t\t\treturn;\n-\t\t}\n-\n-\t\tadd_child(pid, addr, addrlen);\n-\t\treturn;\n-\t}\n+\tcld.argv = (const char **)cld_argv;\n+\tcld.in = incoming;\n+\tcld.out = dup(incoming);\n \n-\tfd[0] = incoming;\n-\tfd[1] = dup(incoming);\n-\texit(execute(fd, addr));\n+\tif (start_command(&cld))\n+\t\tlogerror(\"unable to fork\");\n+\telse\n+\t\tadd_child(&cld, addr, addrlen);\n+\tclose(incoming);\n }\n \n static void child_handler(int signo)\n@@ -934,7 +923,7 @@ int main(int argc, char **argv)\n {\n \tint listen_port = 0;\n \tchar *listen_addr = NULL;\n-\tint inetd_mode = 0;\n+\tint serve_mode = 0, inetd_mode = 0;\n \tconst char *pid_file = NULL, *user_name = NULL, *group_name = NULL;\n \tint detach = 0;\n \tstruct passwd *pass = NULL;\n@@ -960,7 +949,12 @@ int main(int argc, char **argv)\n \t\t\t\tcontinue;\n \t\t\t}\n \t\t}\n+\t\tif (!strcmp(arg, \"--serve\")) {\n+\t\t\tserve_mode = 1;\n+\t\t\tcontinue;\n+\t\t}\n \t\tif (!strcmp(arg, \"--inetd\")) {\n+\t\t\tserve_mode = 1;\n \t\t\tinetd_mode = 1;\n \t\t\tlog_syslog = 1;\n \t\t\tcontinue;\n@@ -1104,13 +1098,13 @@ int main(int argc, char **argv)\n \t\tdie(\"base-path '%s' does not exist or is not a directory\",\n \t\t    base_path);\n \n-\tif (inetd_mode) {\n+\tif (serve_mode) {\n \t\tint fd[2] = { 0, 1 };\n \t\tstruct sockaddr_storage ss;\n \t\tstruct sockaddr *peer = (struct sockaddr *)&ss;\n \t\tsocklen_t slen = sizeof(ss);\n \n-\t\tif (!freopen(\"/dev/null\", \"w\", stderr))\n+\t\tif (inetd_mode && !freopen(\"/dev/null\", \"w\", stderr))\n \t\t\tdie_errno(\"failed to redirect stderr to /dev/null\");\n \n \t\tif (getpeername(0, peer, &slen))\n@@ -1129,5 +1123,12 @@ int main(int argc, char **argv)\n \tif (pid_file)\n \t\tstore_pid(pid_file);\n \n+\t/* prepare argv for serving-processes */\n+\tcld_argv = xmalloc(sizeof (char *) * (argc + 2));\n+\tfor (i = 0; i < argc; ++i)\n+\t\tcld_argv[i] = argv[i];\n+\tcld_argv[argc] = \"--serve\";\n+\tcld_argv[argc+1] = NULL;\n+\n \treturn serve(listen_addr, listen_port, pass, gid);\n }\n-- \n1.6.6.211.g26720\n"},{"id":"131780","messageId":"1263591033-4992-11-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 10/14] daemon: use full buffered mode for stderr","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:29Z","receivedAt":"2010-01-15T21:30:29Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Windows doesn't support line buffered mode for file\nstreams, so let's just use full buffered mode with\na big buffer (\"4096 should be enough for everyone\")\nand add explicit flushing.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n daemon.c |    6 ++++--\n 1 files changed, 4 insertions(+), 2 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 2d63cbc..fc2c150 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -66,12 +66,14 @@ static void logreport(int priority, const char *err, va_list params)\n \t\tsyslog(priority, \"%s\", buf);\n \t} else {\n \t\t/*\n-\t\t * Since stderr is set to linebuffered mode, the\n+\t\t * Since stderr is set to buffered mode, the\n \t\t * logging of different processes will not overlap\n+\t\t * unless they overflow the (rather big) buffers.\n \t\t */\n \t\tfprintf(stderr, \"[%\"PRIuMAX\"] \", (uintmax_t)getpid());\n \t\tvfprintf(stderr, err, params);\n \t\tfputc('\\n', stderr);\n+\t\tfflush(stderr);\n \t}\n }\n \n@@ -1062,7 +1064,7 @@ int main(int argc, char **argv)\n \t\tset_die_routine(daemon_die);\n \t} else\n \t\t/* avoid splitting a message in the middle */\n-\t\tsetvbuf(stderr, NULL, _IOLBF, 0);\n+\t\tsetvbuf(stderr, NULL, _IOFBF, 4096);\n \n \tif (inetd_mode && (group_name || user_name))\n \t\tdie(\"--user and --group are incompatible with --inetd\");\n-- \n1.6.6.211.g26720\n"},{"id":"131781","messageId":"1263591033-4992-12-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 11/14] mingw: compile git-daemon","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:30Z","receivedAt":"2010-01-15T21:30:30Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"--user and --detach are disabled on Windows due to lack of\nfork(), setuid(), setgid(), setsid() and initgroups().\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n Makefile       |    8 +++-----\n compat/mingw.h |    1 +\n daemon.c       |   19 ++++++++++++++-----\n 3 files changed, 18 insertions(+), 10 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex d81b392..cb6c36d 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -390,6 +390,7 @@ EXTRA_PROGRAMS =\n \n # ... and all the rest that could be moved out of bindir to gitexecdir\n PROGRAMS += $(EXTRA_PROGRAMS)\n+PROGRAMS += git-daemon$X\n PROGRAMS += git-fast-import$X\n PROGRAMS += git-hash-object$X\n PROGRAMS += git-imap-send$X\n@@ -986,7 +987,6 @@ ifeq ($(uname_S),Windows)\n \tNO_SVN_TESTS = YesPlease\n \tNO_PERL_MAKEMAKER = YesPlease\n \tRUNTIME_PREFIX = YesPlease\n-\tNO_POSIX_ONLY_PROGRAMS = YesPlease\n \tNO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease\n \tNO_NSEC = YesPlease\n \tUSE_WIN32_MMAP = YesPlease\n@@ -1037,7 +1037,6 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_SVN_TESTS = YesPlease\n \tNO_PERL_MAKEMAKER = YesPlease\n \tRUNTIME_PREFIX = YesPlease\n-\tNO_POSIX_ONLY_PROGRAMS = YesPlease\n \tNO_ST_BLOCKS_IN_STRUCT_STAT = YesPlease\n \tNO_NSEC = YesPlease\n \tUSE_WIN32_MMAP = YesPlease\n@@ -1047,6 +1046,8 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_REGEX = YesPlease\n \tBLK_SHA1 = YesPlease\n \tNO_PYTHON = YesPlease\n+\tNO_INET_PTON = YesPlease\n+\tNO_INET_NTOP = YesPlease\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o\n@@ -1141,9 +1142,6 @@ ifdef ZLIB_PATH\n endif\n EXTLIBS += -lz\n \n-ifndef NO_POSIX_ONLY_PROGRAMS\n-\tPROGRAMS += git-daemon$X\n-endif\n ifndef NO_OPENSSL\n \tOPENSSL_LIBSSL = -lssl\n \tifdef OPENSSLDIR\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex e72c2ee..173bec5 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -7,6 +7,7 @@\n \n typedef int pid_t;\n typedef int socklen_t;\n+typedef unsigned int gid_t;\n #define hstrerror strerror\n \n #define S_IFLNK    0120000 /* Symbolic link */\ndiff --git a/daemon.c b/daemon.c\nindex fc2c150..cdf5c72 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -589,7 +589,7 @@ static struct child {\n \tstruct sockaddr_storage address;\n } *firstborn;\n \n-static void add_child(struct child_process *cld, struct sockaddr *addr, int addrlen)\n+static void add_child(struct child_process *cld, struct sockaddr *addr, socklen_t addrlen)\n {\n \tstruct child *newborn, **cradle;\n \n@@ -646,7 +646,7 @@ static void check_dead_children(void)\n }\n \n char **cld_argv;\n-static void handle(int incoming, struct sockaddr *addr, int addrlen)\n+static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)\n {\n \tstruct child_process cld = { 0 };\n \n@@ -847,7 +847,7 @@ static int service_loop(int socknum, int *socklist)\n \t\tfor (i = 0; i < socknum; i++) {\n \t\t\tif (pfd[i].revents & POLLIN) {\n \t\t\t\tstruct sockaddr_storage ss;\n-\t\t\t\tunsigned int sslen = sizeof(ss);\n+\t\t\t\tsocklen_t sslen = sizeof(ss);\n \t\t\t\tint incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);\n \t\t\t\tif (incoming < 0) {\n \t\t\t\t\tswitch (errno) {\n@@ -879,6 +879,7 @@ static void sanitize_stdfds(void)\n \n static void daemonize(void)\n {\n+#ifndef WIN32\n \tswitch (fork()) {\n \t\tcase 0:\n \t\t\tbreak;\n@@ -893,6 +894,9 @@ static void daemonize(void)\n \tclose(1);\n \tclose(2);\n \tsanitize_stdfds();\n+#else\n+\tdie(\"--detach is not supported on Windows\");\n+#endif\n }\n \n static void store_pid(const char *path)\n@@ -913,10 +917,12 @@ static int serve(char *listen_addr, int listen_port, struct passwd *pass, gid_t\n \t\tdie(\"unable to allocate any listen sockets on host %s port %u\",\n \t\t    listen_addr, listen_port);\n \n+#ifndef WIN32\n \tif (pass && gid &&\n \t    (initgroups(pass->pw_name, gid) || setgid (gid) ||\n \t     setuid(pass->pw_uid)))\n \t\tdie(\"cannot drop privileges\");\n+#endif\n \n \treturn service_loop(socknum, socklist);\n }\n@@ -929,7 +935,6 @@ int main(int argc, char **argv)\n \tconst char *pid_file = NULL, *user_name = NULL, *group_name = NULL;\n \tint detach = 0;\n \tstruct passwd *pass = NULL;\n-\tstruct group *group;\n \tgid_t gid = 0;\n \tint i;\n \n@@ -1078,6 +1083,7 @@ int main(int argc, char **argv)\n \t\tdie(\"--group supplied without --user\");\n \n \tif (user_name) {\n+#ifndef WIN32\n \t\tpass = getpwnam(user_name);\n \t\tif (!pass)\n \t\t\tdie(\"user not found - %s\", user_name);\n@@ -1085,12 +1091,15 @@ int main(int argc, char **argv)\n \t\tif (!group_name)\n \t\t\tgid = pass->pw_gid;\n \t\telse {\n-\t\t\tgroup = getgrnam(group_name);\n+\t\t\tstruct group *group = getgrnam(group_name);\n \t\t\tif (!group)\n \t\t\t\tdie(\"group not found - %s\", group_name);\n \n \t\t\tgid = group->gr_gid;\n \t\t}\n+#else\n+\t\tdie(\"--user is not supported on Windows\");\n+#endif\n \t}\n \n \tif (strict_paths && (!ok_paths || !*ok_paths))\n-- \n1.6.6.211.g26720\n"},{"id":"131782","messageId":"1263591033-4992-13-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 12/14] Improve the mingw getaddrinfo stub to handle more use cases","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:31Z","receivedAt":"2010-01-15T21:30:31Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"From: Martin Storsjö <martin@martin.st>\n\nAllow the node parameter to be null, which is used for getting\nthe default bind address.\n\nAlso allow the hints parameter to be null, to improve standard\nconformance of the stub implementation a little.\n\nSigned-off-by: Martin Storsjo <martin@martin.st>\n---\n compat/mingw.c |   28 +++++++++++++++++++++-------\n 1 files changed, 21 insertions(+), 7 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 89b9b89..02d411a 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -932,19 +932,22 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,\n \t\t\t\t   const struct addrinfo *hints,\n \t\t\t\t   struct addrinfo **res)\n {\n-\tstruct hostent *h = gethostbyname(node);\n+\tstruct hostent *h = NULL;\n \tstruct addrinfo *ai;\n \tstruct sockaddr_in *sin;\n \n-\tif (!h)\n-\t\treturn WSAGetLastError();\n+\tif (node) {\n+\t\th = gethostbyname(node);\n+\t\tif (!h)\n+\t\t\treturn WSAGetLastError();\n+\t}\n \n \tai = xmalloc(sizeof(struct addrinfo));\n \t*res = ai;\n \tai->ai_flags = 0;\n \tai->ai_family = AF_INET;\n-\tai->ai_socktype = hints->ai_socktype;\n-\tswitch (hints->ai_socktype) {\n+\tai->ai_socktype = hints ? hints->ai_socktype : 0;\n+\tswitch (ai->ai_socktype) {\n \tcase SOCK_STREAM:\n \t\tai->ai_protocol = IPPROTO_TCP;\n \t\tbreak;\n@@ -956,14 +959,25 @@ static int WSAAPI getaddrinfo_stub(const char *node, const char *service,\n \t\tbreak;\n \t}\n \tai->ai_addrlen = sizeof(struct sockaddr_in);\n-\tai->ai_canonname = strdup(h->h_name);\n+\tif (hints && (hints->ai_flags & AI_CANONNAME))\n+\t\tai->ai_canonname = h ? strdup(h->h_name) : NULL;\n+\telse\n+\t\tai->ai_canonname = NULL;\n \n \tsin = xmalloc(ai->ai_addrlen);\n \tmemset(sin, 0, ai->ai_addrlen);\n \tsin->sin_family = AF_INET;\n+\t/* Note: getaddrinfo is supposed to allow service to be a string,\n+\t * which should be looked up using getservbyname. This is\n+\t * currently not implemented */\n \tif (service)\n \t\tsin->sin_port = htons(atoi(service));\n-\tsin->sin_addr = *(struct in_addr *)h->h_addr;\n+\tif (h)\n+\t\tsin->sin_addr = *(struct in_addr *)h->h_addr;\n+\telse if (hints && (hints->ai_flags & AI_PASSIVE))\n+\t\tsin->sin_addr.s_addr = INADDR_ANY;\n+\telse\n+\t\tsin->sin_addr.s_addr = INADDR_LOOPBACK;\n \tai->ai_addr = (struct sockaddr *)sin;\n \tai->ai_next = 0;\n \treturn 0;\n-- \n1.6.6.211.g26720\n"},{"id":"131783","messageId":"1263591033-4992-14-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:32Z","receivedAt":"2010-01-15T21:30:32Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Windows doesn't have poll(), and the poll-emulation in\ncompat/mingw.c doesn't support checking multiple sockets.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.h |    7 +++++++\n daemon.c       |   27 ++++++++++++---------------\n 2 files changed, 19 insertions(+), 15 deletions(-)\n\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 173bec5..e515726 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -269,6 +269,13 @@ int mingw_accept(int sockfd, struct sockaddr *sa, socklen_t *sz);\n int mingw_rename(const char*, const char*);\n #define rename mingw_rename\n \n+#undef FD_SET\n+#define FD_SET(fd, set) do { \\\n+\t((fd_set*)(set))->fd_array[((fd_set *)(set))->fd_count++] = _get_osfhandle(fd); \\\n+\t} while(0)\n+#undef FD_ISSET\n+#define FD_ISSET(fd, set) __WSAFDIsSet(_get_osfhandle(fd), (fd_set *)(set))\n+\n #if defined(USE_WIN32_MMAP) || defined(_MSC_VER)\n int mingw_getpagesize(void);\n #define getpagesize mingw_getpagesize\ndiff --git a/daemon.c b/daemon.c\nindex cdf5c72..95cf299 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -818,26 +818,23 @@ static int socksetup(char *listen_addr, int listen_port, int **socklist_p)\n \n static int service_loop(int socknum, int *socklist)\n {\n-\tstruct pollfd *pfd;\n-\tint i;\n-\n-\tpfd = xcalloc(socknum, sizeof(struct pollfd));\n-\n-\tfor (i = 0; i < socknum; i++) {\n-\t\tpfd[i].fd = socklist[i];\n-\t\tpfd[i].events = POLLIN;\n-\t}\n-\n \tsignal(SIGCHLD, child_handler);\n \n \tfor (;;) {\n-\t\tint i;\n+\t\tint i, maxfd = 0;\n+\t\tfd_set fds;\n \n \t\tcheck_dead_children();\n \n-\t\tif (poll(pfd, socknum, -1) < 0) {\n+\t\tFD_ZERO(&fds);\n+\t\tfor (i = 0; i < socknum; i++) {\n+\t\t\tFD_SET(socklist[i], &fds);\n+\t\t\tmaxfd = socklist[i] > maxfd ? socklist[i] : maxfd;\n+\t\t}\n+\n+\t\tif (select(maxfd + 1, &fds, NULL, NULL, NULL) < 0) {\n \t\t\tif (errno != EINTR) {\n-\t\t\t\tlogerror(\"Poll failed, resuming: %s\",\n+\t\t\t\tlogerror(\"select() failed, resuming: %s\",\n \t\t\t\t      strerror(errno));\n \t\t\t\tsleep(1);\n \t\t\t}\n@@ -845,10 +842,10 @@ static int service_loop(int socknum, int *socklist)\n \t\t}\n \n \t\tfor (i = 0; i < socknum; i++) {\n-\t\t\tif (pfd[i].revents & POLLIN) {\n+\t\t\tif (FD_ISSET(socklist[i], &fds)) {\n \t\t\t\tstruct sockaddr_storage ss;\n \t\t\t\tsocklen_t sslen = sizeof(ss);\n-\t\t\t\tint incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);\n+\t\t\t\tint incoming = accept(socklist[i], (struct sockaddr *)&ss, &sslen);\n \t\t\t\tif (incoming < 0) {\n \t\t\t\t\tswitch (errno) {\n \t\t\t\t\tcase EAGAIN:\n-- \n1.6.6.211.g26720\n"},{"id":"131784","messageId":"1263591033-4992-15-git-send-email-kusmabite@gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v2 14/14] daemon: report connection from root-process","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T21:30:33Z","receivedAt":"2010-01-15T21:30:33Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Report incoming connections from the process that\naccept() the connection instead of the handling\nprocess.\n\nThis enables \"Connection from\"-reporting on\nWindows, where getpeername(0, ...) consistently\nfails.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n daemon.c |   70 +++++++++++++++++++++++++++++++++++--------------------------\n 1 files changed, 40 insertions(+), 30 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 95cf299..3423ffa 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -493,33 +493,6 @@ static int execute(int fd[2], struct sockaddr *addr)\n \tstatic char line[1000];\n \tint pktlen, len, i;\n \n-\tif (addr) {\n-\t\tchar addrbuf[256] = \"\";\n-\t\tint port = -1;\n-\n-\t\tif (addr->sa_family == AF_INET) {\n-\t\t\tstruct sockaddr_in *sin_addr = (void *) addr;\n-\t\t\tinet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));\n-\t\t\tport = ntohs(sin_addr->sin_port);\n-#ifndef NO_IPV6\n-\t\t} else if (addr && addr->sa_family == AF_INET6) {\n-\t\t\tstruct sockaddr_in6 *sin6_addr = (void *) addr;\n-\n-\t\t\tchar *buf = addrbuf;\n-\t\t\t*buf++ = '['; *buf = '\\0'; /* stpcpy() is cool */\n-\t\t\tinet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);\n-\t\t\tstrcat(buf, \"]\");\n-\n-\t\t\tport = ntohs(sin6_addr->sin6_port);\n-#endif\n-\t\t}\n-\t\tloginfo(\"Connection from %s:%d\", addrbuf, port);\n-\t\tsetenv(\"REMOTE_ADDR\", addrbuf, 1);\n-\t}\n-\telse {\n-\t\tunsetenv(\"REMOTE_ADDR\");\n-\t}\n-\n \talarm(init_timeout ? init_timeout : timeout);\n \tpktlen = packet_read_line(fd[0], line, sizeof(line));\n \talarm(0);\n@@ -645,10 +618,35 @@ static void check_dead_children(void)\n \t\t\tcradle = &blanket->next;\n }\n \n+static char *get_addrstr(int *port, struct sockaddr *addr)\n+{\n+\tstatic char addrbuf[256] = \"\";\n+\tif (addr->sa_family == AF_INET) {\n+\t\tstruct sockaddr_in *sin_addr = (void *) addr;\n+\t\tinet_ntop(addr->sa_family, &sin_addr->sin_addr, addrbuf, sizeof(addrbuf));\n+\t\t*port = ntohs(sin_addr->sin_port);\n+#ifndef NO_IPV6\n+\t} else if (addr && addr->sa_family == AF_INET6) {\n+\t\tstruct sockaddr_in6 *sin6_addr = (void *) addr;\n+\n+\t\tchar *buf = addrbuf;\n+\t\t*buf++ = '['; *buf = '\\0'; /* stpcpy() is cool */\n+\t\tinet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf, sizeof(addrbuf) - 1);\n+\t\tstrcat(buf, \"]\");\n+\n+\t\t*port = ntohs(sin6_addr->sin6_port);\n+#endif\n+\t}\n+\treturn addrbuf;\n+}\n+\n char **cld_argv;\n static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)\n {\n \tstruct child_process cld = { 0 };\n+\tchar *addrstr, envbuf[300] = \"REMOTE_ADDR=\";\n+\tchar *env[] = { envbuf, NULL };\n+\tint port = -1;\n \n \tif (max_connections && live_children >= max_connections) {\n \t\tkill_some_child();\n@@ -661,14 +659,21 @@ static void handle(int incoming, struct sockaddr *addr, socklen_t addrlen)\n \t\t}\n \t}\n \n+\taddrstr = get_addrstr(&port, addr);\n+\tstrcat(envbuf, addrstr);\n+\n+\tcld.env = (const char **)env;\n \tcld.argv = (const char **)cld_argv;\n \tcld.in = incoming;\n \tcld.out = dup(incoming);\n \n \tif (start_command(&cld))\n \t\tlogerror(\"unable to fork\");\n-\telse\n+\telse {\n+\t\tloginfo(\"[%\"PRIuMAX\"] Connection from %s:%d\",\n+\t\t    (uintmax_t)cld.pid, addrstr, port);\n \t\tadd_child(&cld, addr, addrlen);\n+\t}\n \tclose(incoming);\n }\n \n@@ -1115,8 +1120,13 @@ int main(int argc, char **argv)\n \t\tif (inetd_mode && !freopen(\"/dev/null\", \"w\", stderr))\n \t\t\tdie_errno(\"failed to redirect stderr to /dev/null\");\n \n-\t\tif (getpeername(0, peer, &slen))\n-\t\t\tpeer = NULL;\n+\t\tif (!getpeername(0, peer, &slen)) {\n+\t\t\tint port = -1;\n+\t\t\tchar *addrstr = get_addrstr(&port, peer);\n+\t\t\tsetenv(\"REMOTE_ADDR\", addrstr, 1);\n+\t\t\tloginfo(\"[%\"PRIuMAX\"] Connection from %s:%d\",\n+\t\t\t    (uintmax_t)getpid(), addrstr, port);\n+\t\t}\n \n \t\treturn execute(fd, peer);\n \t}\n-- \n1.6.6.211.g26720\n"},{"id":"131791","messageId":"201001152327.23189.j6t@kdbg.org","threadId":"22235","inReplyTo":"1263591033-4992-1-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v2 00/14] daemon-win32","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-15T22:27:23Z","receivedAt":"2010-01-15T22:27:23Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"A very nicely done series. Thank you very much!\n\nOn Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n> Here's the long overdue v2 of my daemon-win32 attempt. A lot\n> has happened since v1. Most importantly, I abandoned using\n> the async API to replace fork(), and went for explicitly\n> spawning child process that handle the connection.\n\nIOW, you run git-daemon recursively in inetd mode (almost). Let's see what \npeople say about this approach.\n\n-- Hannes\n"},{"id":"131793","messageId":"201001152328.28260.j6t@kdbg.org","threadId":"22235","inReplyTo":"1263591033-4992-6-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v2 05/14] mingw: support waitpid with pid > 0 and WNOHANG","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-15T22:28:28Z","receivedAt":"2010-01-15T22:28:28Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>  static inline int waitpid(pid_t pid, int *status, unsigned options)\n>  {\n> +\tif (pid > 0 && options & WNOHANG) {\n> +\t\tif (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n> +\t\t\treturn 0;\n> +\t\toptions &= ~WNOHANG;\n> +\t}\n> +\n>  \tif (options == 0)\n>  \t\treturn _cwait(status, pid, 0);\n>  \terrno = EINVAL;\n\nWith this change, and in particular the one in the next patch, this function \ngrows too large to be 'static inline'.\n\n-- Hannes\n"},{"id":"131795","messageId":"201001152330.06083.j6t@kdbg.org","threadId":"22235","inReplyTo":"1263591033-4992-7-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v2 06/14] mingw: use real pid","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-15T22:30:05Z","receivedAt":"2010-01-15T22:30:05Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n> @@ -729,7 +729,7 @@ static pid_t mingw_spawnve(const char *cmd, const char\n> **argv, char **env, return -1;\n>  \t}\n>  \tCloseHandle(pi.hThread);\n> -\treturn (pid_t)pi.hProcess;\n> +\treturn (pid_t)pi.dwProcessId;\n>  }\n\nYou are not using the pi.hProcess anymore, so you must close it.\n\n-- Hannes\n"},{"id":"131796","messageId":"201001152331.39199.j6t@kdbg.org","threadId":"22235","inReplyTo":"1263591033-4992-8-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v2 07/14] mingw: add kill emulation","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-15T22:31:39Z","receivedAt":"2010-01-15T22:31:39Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n> +int mingw_kill(pid_t pid, int sig)\n> +{\n> ...\n> +\t\tCloseHandle(h);\n> +\t\terrno = err_win_to_posix(GetLastError());\n\nSet errno before CloseHandle() to get the correct error.\n\n-- Hannes\n"},{"id":"131797","messageId":"201001152336.20662.j6t@kdbg.org","threadId":"22235","inReplyTo":"1263591033-4992-9-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v2 08/14] daemon: use explicit file descriptor","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-15T22:36:20Z","receivedAt":"2010-01-15T22:36:20Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n> This patch adds support to specify an explicit file\n> descriotor for communication with the client, instead\n> of using stdin/stdout.\n>\n> This will be useful for the Windows port, because it\n> will use threads instead of fork() to serve multiple\n> clients, making it impossible to reuse stdin/stdout.\n\nThis statement is a bit outdated.\n\n-- Hannes\n"},{"id":"131799","messageId":"201001152342.35081.j6t@kdbg.org","threadId":"22235","inReplyTo":"1263591033-4992-10-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v2 09/14] daemon: use run-command api for async serving","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-15T22:42:34Z","receivedAt":"2010-01-15T22:42:34Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n> fork() is only available on POSIX, so to support git-daemon\n> on Windows we have to use something else. Conveniently\n> enough, we have an API for async operation already.\n\nI had a huh?-moment when I read this statement. This patch does not use what \nwe call 'async', but start_command().\n\n-- Hannes\n"},{"id":"131801","messageId":"201001152349.06418.j6t@kdbg.org","threadId":"22235","inReplyTo":"1263591033-4992-14-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-15T22:49:06Z","receivedAt":"2010-01-15T22:49:06Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n> +#undef FD_SET\n> +#define FD_SET(fd, set) do { \\\n> +\t((fd_set*)(set))->fd_array[((fd_set *)(set))->fd_count++] =\n> _get_osfhandle(fd); \\ +\t} while(0)\n> +#undef FD_ISSET\n> +#define FD_ISSET(fd, set) __WSAFDIsSet(_get_osfhandle(fd), (fd_set\n> *)(set)) +\n\nI'm worried about the internals that you have to use here. Isn't it possible \nsave the original macro text and use it in the new definition, like (this is \nfor exposition only):\n\n#define ORIG_FD_SET(fd, set) FD_SET(fd, set)\n#undef FD_SET\n#define FD_SET(fd, set) ORIG_FD_SET(_get_osfhandle(fd), set)\n\nAnother approach would be to extend the poll emulation such that it uses \nselect if all FDs to wait for are sockets, and I think this would be the case \nin this application.\n\n-- Hannes\n"},{"id":"131802","messageId":"40aa078e1001151451t657dcbdbk202c7374ac7f6724@mail.gmail.com","threadId":"22235","inReplyTo":"201001152327.23189.j6t@kdbg.org","subject":"Re: [PATCH v2 00/14] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T22:51:15Z","receivedAt":"2010-01-15T22:51:15Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Jan 15, 2010 at 11:27 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> A very nicely done series. Thank you very much!\n>\n> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>> Here's the long overdue v2 of my daemon-win32 attempt. A lot\n>> has happened since v1. Most importantly, I abandoned using\n>> the async API to replace fork(), and went for explicitly\n>> spawning child process that handle the connection.\n>\n> IOW, you run git-daemon recursively in inetd mode (almost). Let's see what\n> people say about this approach.\n>\n> -- Hannes\n>\n\nYes. Or, a subset of the inetd-mode.\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131803","messageId":"40aa078e1001151453i3576a345k217944c38887b61f@mail.gmail.com","threadId":"22235","inReplyTo":"201001152330.06083.j6t@kdbg.org","subject":"Re: [PATCH v2 06/14] mingw: use real pid","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T22:53:54Z","receivedAt":"2010-01-15T22:53:54Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Jan 15, 2010 at 11:30 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>> @@ -729,7 +729,7 @@ static pid_t mingw_spawnve(const char *cmd, const char\n>> **argv, char **env, return -1;\n>>       }\n>>       CloseHandle(pi.hThread);\n>> -     return (pid_t)pi.hProcess;\n>> +     return (pid_t)pi.dwProcessId;\n>>  }\n>\n> You are not using the pi.hProcess anymore, so you must close it.\n>\n\nNo. If I do, the pid becomes invalid after the process is finished,\nand waitpid won't work. I couldn't find anywhere were we actually were\nclosing the handle, even after it was finished. So I don't think we\nleak any more than we already did (for non-daemon purposes).\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131804","messageId":"9d6091531001151457v4c446b61k40c93f7c6180683d@mail.gmail.com","threadId":"22235","inReplyTo":"1263591033-4992-3-git-send-email-kusmabite@gmail.com","subject":"Re: [msysGit] [PATCH v2 02/14] mingw: implement syslog","fromName":"Janos Laube","fromEmail":"janos.dev@gmail.com","sentAt":"2010-01-15T22:57:07Z","receivedAt":"2010-01-15T22:57:07Z","isPatch":true,"sender":{"key":"janos.dev@gmail.com","avatar":"https://gravatar.com/avatar/549ab81cf6daf46c9c0124bdb14d2d3260329bac3821c209ef7b5ebffc7cb006?d=mp&s=160"},"body":"> +static HANDLE ms_eventlog;\n> +\n> +void openlog(const char *ident, int logopt, int facility)\n> +{\n> +       if (ms_eventlog)\n> +               return;\n> +       ms_eventlog = RegisterEventSourceA(NULL, ident);\n> +}\n\nmaybe make ms_eventlog thread local?\nfor example:\n\nstatic __thread HANDLE ms_eventlog;\n\nthis would break compilation with msvc tho.\n\njanos\n"},{"id":"131805","messageId":"40aa078e1001151501s462802ffua3aec600ed38f516@mail.gmail.com","threadId":"22235","inReplyTo":"9d6091531001151457v4c446b61k40c93f7c6180683d@mail.gmail.com","subject":"Re: [msysGit] [PATCH v2 02/14] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T23:01:53Z","receivedAt":"2010-01-15T23:01:53Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Jan 15, 2010 at 11:57 PM, Janos Laube <janos.dev@gmail.com> wrote:\n>> +static HANDLE ms_eventlog;\n>> +\n>> +void openlog(const char *ident, int logopt, int facility)\n>> +{\n>> +       if (ms_eventlog)\n>> +               return;\n>> +       ms_eventlog = RegisterEventSourceA(NULL, ident);\n>> +}\n>\n> maybe make ms_eventlog thread local?\n> for example:\n>\n> static __thread HANDLE ms_eventlog;\n>\n> this would break compilation with msvc tho.\n>\n> janos\n>\n\nSince the code that use it isn't multi-threaded, I fail to see the\npoint. In fact even if it were, I'm not sure I see the big point...\nespecially since the \"__thread\"-keyword isn't used (AFAICT) at all in\nthe git source code so far.\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131807","messageId":"40aa078e1001151508j208fa50boc5565a3be6bef893@mail.gmail.com","threadId":"22235","inReplyTo":"201001152349.06418.j6t@kdbg.org","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T23:08:28Z","receivedAt":"2010-01-15T23:08:28Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Jan 15, 2010 at 11:49 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>> +#undef FD_SET\n>> +#define FD_SET(fd, set) do { \\\n>> +     ((fd_set*)(set))->fd_array[((fd_set *)(set))->fd_count++] =\n>> _get_osfhandle(fd); \\ +       } while(0)\n>> +#undef FD_ISSET\n>> +#define FD_ISSET(fd, set) __WSAFDIsSet(_get_osfhandle(fd), (fd_set\n>> *)(set)) +\n>\n> I'm worried about the internals that you have to use here. Isn't it possible\n> save the original macro text and use it in the new definition, like (this is\n> for exposition only):\n>\n> #define ORIG_FD_SET(fd, set) FD_SET(fd, set)\n> #undef FD_SET\n> #define FD_SET(fd, set) ORIG_FD_SET(_get_osfhandle(fd), set)\n>\n\nRedefining it is indeed fishy - I guess I should also have noted that\nI even stripped the code down slightly (compared to the original).\n\nI'm no preprocessor wizard, but I'll give it a stab.\n\n> Another approach would be to extend the poll emulation such that it uses\n> select if all FDs to wait for are sockets, and I think this would be the case\n> in this application.\n>\n\nThe problem with that is differentiating between pipes and sockets.\nGetFileType() returns FILE_TYPE_PIPE for sockets (ugh). I did find\nsome code in gnulib that used WSAEnumNetworkEvents() to differentiate\nbetween them, but I find this quite hacky.\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131808","messageId":"9d6091531001151509m52cd1f4dk4035d313ca2de292@mail.gmail.com","threadId":"22235","inReplyTo":"40aa078e1001151501s462802ffua3aec600ed38f516@mail.gmail.com","subject":"Re: [msysGit] [PATCH v2 02/14] mingw: implement syslog","fromName":"Janos Laube","fromEmail":"janos.dev@gmail.com","sentAt":"2010-01-15T23:09:14Z","receivedAt":"2010-01-15T23:09:14Z","isPatch":true,"sender":{"key":"janos.dev@gmail.com","avatar":"https://gravatar.com/avatar/549ab81cf6daf46c9c0124bdb14d2d3260329bac3821c209ef7b5ebffc7cb006?d=mp&s=160"},"body":"> Since the code that use it isn't multi-threaded, I fail to see the\n> point. In fact even if it were, I'm not sure I see the big point...\n> especially since the \"__thread\"-keyword isn't used (AFAICT) at all in\n> the git source code so far.\n\nthat's why i have put a question mark behind my sentence. it was just\nan idea :-). it would allow different threads to be an own event\nsource. but yes, i wasn't sure how much git makes use of threads. if\nit doesn't, it does not make much sense at the moment, indeed.\n\njanos\n"},{"id":"131811","messageId":"40aa078e1001151523o538b44c7x95def3447650eea4@mail.gmail.com","threadId":"22235","inReplyTo":"40aa078e1001151508j208fa50boc5565a3be6bef893@mail.gmail.com","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-15T23:23:46Z","receivedAt":"2010-01-15T23:23:46Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sat, Jan 16, 2010 at 12:08 AM, Erik Faye-Lund\n<kusmabite@googlemail.com> wrote:\n> On Fri, Jan 15, 2010 at 11:49 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n>> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>>> +#undef FD_SET\n>>> +#define FD_SET(fd, set) do { \\\n>>> +     ((fd_set*)(set))->fd_array[((fd_set *)(set))->fd_count++] =\n>>> _get_osfhandle(fd); \\ +       } while(0)\n>>> +#undef FD_ISSET\n>>> +#define FD_ISSET(fd, set) __WSAFDIsSet(_get_osfhandle(fd), (fd_set\n>>> *)(set)) +\n>>\n>> I'm worried about the internals that you have to use here. Isn't it possible\n>> save the original macro text and use it in the new definition, like (this is\n>> for exposition only):\n>>\n>> #define ORIG_FD_SET(fd, set) FD_SET(fd, set)\n>> #undef FD_SET\n>> #define FD_SET(fd, set) ORIG_FD_SET(_get_osfhandle(fd), set)\n>>\n>\n> Redefining it is indeed fishy - I guess I should also have noted that\n> I even stripped the code down slightly (compared to the original).\n>\n> I'm no preprocessor wizard, but I'll give it a stab.\n>\n\nThe following worked for me:\n\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex e515726..ea15967 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -269,10 +269,13 @@ int mingw_accept(int sockfd, struct sockaddr\n*sa, socklen_t *sz);\n int mingw_rename(const char*, const char*);\n #define rename mingw_rename\n\n+static inline void mingw_fd_set(int fd, fd_set *set)\n+{\n+\tFD_SET(_get_osfhandle(fd), set);\n+}\n #undef FD_SET\n-#define FD_SET(fd, set) do { \\\n-\t((fd_set*)(set))->fd_array[((fd_set *)(set))->fd_count++] =\n_get_osfhandle(fd); \\\n-\t} while(0)\n+#define FD_SET(a,b) mingw_fd_set(a,b)\n+\n #undef FD_ISSET\n #define FD_ISSET(fd, set) __WSAFDIsSet(_get_osfhandle(fd), (fd_set *)(set))\n\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131857","messageId":"201001160903.25162.j6t@kdbg.org","threadId":"22235","inReplyTo":"40aa078e1001151453i3576a345k217944c38887b61f@mail.gmail.com","subject":"Re: [PATCH v2 06/14] mingw: use real pid","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-16T08:03:25Z","receivedAt":"2010-01-16T08:03:25Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n> On Fri, Jan 15, 2010 at 11:30 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> > On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n> >> @@ -729,7 +729,7 @@ static pid_t mingw_spawnve(const char *cmd, const\n> >> char **argv, char **env, return -1;\n> >>       }\n> >>       CloseHandle(pi.hThread);\n> >> -     return (pid_t)pi.hProcess;\n> >> +     return (pid_t)pi.dwProcessId;\n> >>  }\n> >\n> > You are not using the pi.hProcess anymore, so you must close it.\n>\n> No. If I do, the pid becomes invalid after the process is finished,\n> and waitpid won't work. I couldn't find anywhere were we actually were\n> closing the handle, even after it was finished. So I don't think we\n> leak any more than we already did (for non-daemon purposes).\n\nPreviously, this handle was closed by _cwait() (it was the \"pid\"), so we \ndidn't leak it.\n\nI somehow thought that you need the process ID instead of the handle for \nTerminateProcess, but now I see that this is not the case (it takes the \nhandle). So I don't see the point of this change anymore. You say the process \nhandle \"does not work consistently with getpid\", but I don't know what you \nmean. Please explain.\n\n-- Hannes\n"},{"id":"131858","messageId":"201001160906.26270.j6t@kdbg.org","threadId":"22235","inReplyTo":"40aa078e1001151523o538b44c7x95def3447650eea4@mail.gmail.com","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-16T08:06:26Z","receivedAt":"2010-01-16T08:06:26Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n> +static inline void mingw_fd_set(int fd, fd_set *set)\n> +{\n> +\tFD_SET(_get_osfhandle(fd), set);\n> +}\n>  #undef FD_SET\n> +#define FD_SET(a,b) mingw_fd_set(a,b)\n> +\n>  #undef FD_ISSET\n>  #define FD_ISSET(fd, set) __WSAFDIsSet(_get_osfhandle(fd), (fd_set\n> *)(set))\n\nAh, yes, how obvious ;) You are going to do the same with FD_ISSET as well, \naren't you?\n\n-- Hannes\n"},{"id":"131859","messageId":"201001160908.33996.j6t@kdbg.org","threadId":"22235","inReplyTo":"40aa078e1001151508j208fa50boc5565a3be6bef893@mail.gmail.com","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-16T08:08:33Z","receivedAt":"2010-01-16T08:08:33Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n> The problem with that is differentiating between pipes and sockets.\n> GetFileType() returns FILE_TYPE_PIPE for sockets (ugh). I did find\n> some code in gnulib that used WSAEnumNetworkEvents() to differentiate\n> between them, but I find this quite hacky.\n\nWouldn't it be possible to call getsockopt(), and if it returns ENOTSOCK \n(WSAENOTSOCK), then it is a pipe?\n\n-- Hannes\n"},{"id":"131860","messageId":"40aa078e1001160112k68c0daafnd6abcb715e1176fe@mail.gmail.com","threadId":"22235","inReplyTo":"201001160903.25162.j6t@kdbg.org","subject":"Re: [PATCH v2 06/14] mingw: use real pid","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-16T09:12:47Z","receivedAt":"2010-01-16T09:12:47Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sat, Jan 16, 2010 at 9:03 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>> On Fri, Jan 15, 2010 at 11:30 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n>> > On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>> >> @@ -729,7 +729,7 @@ static pid_t mingw_spawnve(const char *cmd, const\n>> >> char **argv, char **env, return -1;\n>> >>       }\n>> >>       CloseHandle(pi.hThread);\n>> >> -     return (pid_t)pi.hProcess;\n>> >> +     return (pid_t)pi.dwProcessId;\n>> >>  }\n>> >\n>> > You are not using the pi.hProcess anymore, so you must close it.\n>>\n>> No. If I do, the pid becomes invalid after the process is finished,\n>> and waitpid won't work. I couldn't find anywhere were we actually were\n>> closing the handle, even after it was finished. So I don't think we\n>> leak any more than we already did (for non-daemon purposes).\n>\n> Previously, this handle was closed by _cwait() (it was the \"pid\"), so we\n> didn't leak it.\n\nOh, I see. My planned route with this (before I looked for where the\nhandle was closed), was to maintain some sort of list of each started\nPID and their handle, and lookup in that list instead of using\nOpenProcess. I guess that would solve the problem here, but it feels a\nbit nasty. Not as nasty as introducing a leak, though.\n\n>\n> I somehow thought that you need the process ID instead of the handle for\n> TerminateProcess, but now I see that this is not the case (it takes the\n> handle). So I don't see the point of this change anymore. You say the process\n> handle \"does not work consistently with getpid\", but I don't know what you\n> mean. Please explain.\n\ngetpid() returns the real PID, and is used for prefixing each logged\nmessage by git-daemon. However, the root process reports whenever a\nnew process is started or has terminated using the PID returned by\nmingw_spawnve(), and this handle does not match up with the PID that\ngetpid() reports. Thus it becomes impossible to tell which reported\nerror belongs to which client.\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131861","messageId":"40aa078e1001160114k5ce0414et7cd645724973609b@mail.gmail.com","threadId":"22235","inReplyTo":"201001160908.33996.j6t@kdbg.org","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-16T09:14:23Z","receivedAt":"2010-01-16T09:14:23Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sat, Jan 16, 2010 at 9:08 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n>> The problem with that is differentiating between pipes and sockets.\n>> GetFileType() returns FILE_TYPE_PIPE for sockets (ugh). I did find\n>> some code in gnulib that used WSAEnumNetworkEvents() to differentiate\n>> between them, but I find this quite hacky.\n>\n> Wouldn't it be possible to call getsockopt(), and if it returns ENOTSOCK\n> (WSAENOTSOCK), then it is a pipe?\n>\n> -- Hannes\n>\n\nI read reports that this didn't work in Wine. Not that I care that\nmuch about Wine.\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131864","messageId":"40aa078e1001160126q34bc066as3adb9b61eac690d@mail.gmail.com","threadId":"22235","inReplyTo":"201001160906.26270.j6t@kdbg.org","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-16T09:26:29Z","receivedAt":"2010-01-16T09:26:29Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sat, Jan 16, 2010 at 9:06 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n>> +static inline void mingw_fd_set(int fd, fd_set *set)\n>> +{\n>> +     FD_SET(_get_osfhandle(fd), set);\n>> +}\n>>  #undef FD_SET\n>> +#define FD_SET(a,b) mingw_fd_set(a,b)\n>> +\n>>  #undef FD_ISSET\n>>  #define FD_ISSET(fd, set) __WSAFDIsSet(_get_osfhandle(fd), (fd_set\n>> *)(set))\n>\n> Ah, yes, how obvious ;) You are going to do the same with FD_ISSET as well,\n> aren't you?\n>\n> -- Hannes\n>\n\nDo I really need to? There's already a single function for that, with\nno \"ugly hidden internals\" there; __WSAFDIsSet() is documented in\nMSDN. I mean, Sure... I could... I just don't see the point.\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131868","messageId":"201001161138.36535.j6t@kdbg.org","threadId":"22235","inReplyTo":"40aa078e1001160126q34bc066as3adb9b61eac690d@mail.gmail.com","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-16T10:38:36Z","receivedAt":"2010-01-16T10:38:36Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n> On Sat, Jan 16, 2010 at 9:06 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n> > On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n> >> +static inline void mingw_fd_set(int fd, fd_set *set)\n> >> +{\n> >> +     FD_SET(_get_osfhandle(fd), set);\n> >> +}\n> >>  #undef FD_SET\n> >> +#define FD_SET(a,b) mingw_fd_set(a,b)\n> >> +\n> >>  #undef FD_ISSET\n> >>  #define FD_ISSET(fd, set) __WSAFDIsSet(_get_osfhandle(fd), (fd_set\n> >> *)(set))\n> >\n> > Ah, yes, how obvious ;) You are going to do the same with FD_ISSET as\n> > well, aren't you?\n>\n> Do I really need to? There's already a single function for that, with\n> no \"ugly hidden internals\" there; __WSAFDIsSet() is documented in\n> MSDN. I mean, Sure... I could... I just don't see the point.\n\n__WSAFDIsSet is \"ugly hidden internals\" and we should not rely on it when we \ncan use the official FD_ISSET for our own FD_ISSET.\n\n-- Hannes\n"},{"id":"131869","messageId":"201001161144.55263.j6t@kdbg.org","threadId":"22235","inReplyTo":"40aa078e1001160114k5ce0414et7cd645724973609b@mail.gmail.com","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-16T10:44:55Z","receivedAt":"2010-01-16T10:44:55Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n> On Sat, Jan 16, 2010 at 9:08 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n> > Wouldn't it be possible to call getsockopt(), and if it returns ENOTSOCK\n> > (WSAENOTSOCK), then it is a pipe?\n>\n> I read reports that this didn't work in Wine. Not that I care that\n> much about Wine.\n\nWhat does it mean that \"it does not work\"? Is it that it does not return \nENOTSOCK, so that we mistake pipes as sockets?\n\n-- Hannes\n"},{"id":"131871","messageId":"40aa078e1001160259h7f82b702u405a2bed515cfd81@mail.gmail.com","threadId":"22235","inReplyTo":"201001161144.55263.j6t@kdbg.org","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-16T10:59:51Z","receivedAt":"2010-01-16T10:59:51Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sat, Jan 16, 2010 at 11:44 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n>> On Sat, Jan 16, 2010 at 9:08 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n>> > Wouldn't it be possible to call getsockopt(), and if it returns ENOTSOCK\n>> > (WSAENOTSOCK), then it is a pipe?\n>>\n>> I read reports that this didn't work in Wine. Not that I care that\n>> much about Wine.\n>\n> What does it mean that \"it does not work\"? Is it that it does not return\n> ENOTSOCK, so that we mistake pipes as sockets?\n>\n> -- Hannes\n>\n\nYes, according to the gnulib sources[1], getsockopt returns 0 for pipes.\n\n[1]: http://git.savannah.gnu.org/gitweb/?p=gnulib.git;a=blob;f=lib/poll.c;h=90d99d92dca5d7ce2f31097e4b8fc06a83aae245;hb=HEAD#l80\n\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131873","messageId":"40aa078e1001160305y17b46a6dtc4959e5255c7acae@mail.gmail.com","threadId":"22235","inReplyTo":"201001161138.36535.j6t@kdbg.org","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-16T11:05:09Z","receivedAt":"2010-01-16T11:05:09Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sat, Jan 16, 2010 at 11:38 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n>> On Sat, Jan 16, 2010 at 9:06 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n>> > On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n>> >> +static inline void mingw_fd_set(int fd, fd_set *set)\n>> >> +{\n>> >> +     FD_SET(_get_osfhandle(fd), set);\n>> >> +}\n>> >>  #undef FD_SET\n>> >> +#define FD_SET(a,b) mingw_fd_set(a,b)\n>> >> +\n>> >>  #undef FD_ISSET\n>> >>  #define FD_ISSET(fd, set) __WSAFDIsSet(_get_osfhandle(fd), (fd_set\n>> >> *)(set))\n>> >\n>> > Ah, yes, how obvious ;) You are going to do the same with FD_ISSET as\n>> > well, aren't you?\n>>\n>> Do I really need to? There's already a single function for that, with\n>> no \"ugly hidden internals\" there; __WSAFDIsSet() is documented in\n>> MSDN. I mean, Sure... I could... I just don't see the point.\n>\n> __WSAFDIsSet is \"ugly hidden internals\" and we should not rely on it when we\n> can use the official FD_ISSET for our own FD_ISSET.\n>\n> -- Hannes\n>\n\n...but __WSAFDIsSet() seems to be every bit as official on Windows as\nFD_ISSET() (documented in msdn, without any notes not to use it), so I\nstill don't really see the point.\n\nHowever, I don't personally care one way or the other, so just doing\nit is probably less work than convincing you that I don't have to ;)\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131874","messageId":"m26372uw5k.fsf@igel.home","threadId":"22235","inReplyTo":"40aa078e1001160305y17b46a6dtc4959e5255c7acae@mail.gmail.com","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Andreas Schwab","fromEmail":"schwab@linux-m68k.org","sentAt":"2010-01-16T11:27:51Z","receivedAt":"2010-01-16T11:27:51Z","isPatch":true,"sender":{"key":"schwab@linux-m68k.org","avatar":"https://avatars.githubusercontent.com/u/2175493?v=4"},"body":"Erik Faye-Lund <kusmabite@googlemail.com> writes:\n\n> ...but __WSAFDIsSet() seems to be every bit as official on Windows as\n> FD_ISSET() (documented in msdn, without any notes not to use it), so I\n> still don't really see the point.\n\nThe fact that it starts with two underscores suggests that it is kinda\ninternal.\n\nAndreas.\n\n-- \nAndreas Schwab, schwab@linux-m68k.org\nGPG Key fingerprint = 58CA 54C7 6D53 942B 1756  01D3 44D5 214B 8276 4ED5\n\"And now for something completely different.\"\n"},{"id":"131875","messageId":"40aa078e1001160343t3001c6e1r89f793ac2cb3aebc@mail.gmail.com","threadId":"22235","inReplyTo":"m26372uw5k.fsf@igel.home","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-16T11:43:36Z","receivedAt":"2010-01-16T11:43:36Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"(Note: I'll argue only for the sake for the argument here, I've\nalready pretty much decided to follow Hannes' suggestion)\n\nOn Sat, Jan 16, 2010 at 12:27 PM, Andreas Schwab <schwab@linux-m68k.org> wrote:\n> The fact that it starts with two underscores suggests that it is kinda\n> internal.\n>\n\nBut the fact that it is documented more than suggests that it isn't.\nNot any more, anyhow. This is pretty much how winapi works. Internal\nstuff isn't documented, once it's documented it isn't internal\nanymore. In fact, winapi doesn't really deal with \"internal\" and\n\"external\" functions, it deals with documented and undocumented. Some\ndocumented functions/features have documented compatibility issues.\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131878","messageId":"201001161336.20703.j6t@kdbg.org","threadId":"22235","inReplyTo":"40aa078e1001160305y17b46a6dtc4959e5255c7acae@mail.gmail.com","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-16T12:36:20Z","receivedAt":"2010-01-16T12:36:20Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n> ...but __WSAFDIsSet() seems to be every bit as official on Windows as\n> FD_ISSET() (documented in msdn, without any notes not to use it), so I\n> still don't really see the point.\n\nI didn't know nor check whether it is documented, but assumed from the '__' \nthat it must be internal. Being documented makes a big difference. I'm fine \nwith either solution.\n\n-- Hannes\n"},{"id":"131910","messageId":"40aa078e1001161331o115065dax98642ed2054f9b9d@mail.gmail.com","threadId":"22235","inReplyTo":"201001161336.20703.j6t@kdbg.org","subject":"Re: [PATCH v2 13/14] daemon: use select() instead of poll()","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-16T21:31:49Z","receivedAt":"2010-01-16T21:31:49Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sat, Jan 16, 2010 at 1:36 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Samstag, 16. Januar 2010, Erik Faye-Lund wrote:\n>> ...but __WSAFDIsSet() seems to be every bit as official on Windows as\n>> FD_ISSET() (documented in msdn, without any notes not to use it), so I\n>> still don't really see the point.\n>\n> I didn't know nor check whether it is documented, but assumed from the '__'\n> that it must be internal. Being documented makes a big difference. I'm fine\n> with either solution.\n>\n\nOK, in that case, I'll leave it as it is. The current code is slightly\nmore tested (I've been using it for some weeks), and I'm slightly lazy\n;)\n\nBut I'll update FD_SET...\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131912","messageId":"40aa078e1001161352w46f655cam3a2743ebf1d8afff@mail.gmail.com","threadId":"22235","inReplyTo":"201001152336.20662.j6t@kdbg.org","subject":"Re: [PATCH v2 08/14] daemon: use explicit file descriptor","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-16T21:52:54Z","receivedAt":"2010-01-16T21:52:54Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Jan 15, 2010 at 11:36 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>> This patch adds support to specify an explicit file\n>> descriotor for communication with the client, instead\n>> of using stdin/stdout.\n>>\n>> This will be useful for the Windows port, because it\n>> will use threads instead of fork() to serve multiple\n>> clients, making it impossible to reuse stdin/stdout.\n>\n> This statement is a bit outdated.\n>\n> -- Hannes\n>\n\nHeh, yeah. I apparently missed that this patch isn't needed at all any more.\n\nThanks for noticing something was off :)\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131913","messageId":"40aa078e1001161356i1efc7e42q5139614d95bc181@mail.gmail.com","threadId":"22235","inReplyTo":"201001152331.39199.j6t@kdbg.org","subject":"Re: [PATCH v2 07/14] mingw: add kill emulation","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-16T21:56:49Z","receivedAt":"2010-01-16T21:56:49Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Jan 15, 2010 at 11:31 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>> +int mingw_kill(pid_t pid, int sig)\n>> +{\n>> ...\n>> +             CloseHandle(h);\n>> +             errno = err_win_to_posix(GetLastError());\n>\n> Set errno before CloseHandle() to get the correct error.\n>\n> -- Hannes\n>\n\nThanks for pointing that out. Corrected locally.\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"131914","messageId":"40aa078e1001161357m1799478bk35c35077f8836e9e@mail.gmail.com","threadId":"22235","inReplyTo":"201001152328.28260.j6t@kdbg.org","subject":"Re: [PATCH v2 05/14] mingw: support waitpid with pid > 0 and WNOHANG","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-16T21:57:19Z","receivedAt":"2010-01-16T21:57:19Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Fri, Jan 15, 2010 at 11:28 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>>  static inline int waitpid(pid_t pid, int *status, unsigned options)\n>>  {\n>> +     if (pid > 0 && options & WNOHANG) {\n>> +             if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n>> +                     return 0;\n>> +             options &= ~WNOHANG;\n>> +     }\n>> +\n>>       if (options == 0)\n>>               return _cwait(status, pid, 0);\n>>       errno = EINVAL;\n>\n> With this change, and in particular the one in the next patch, this function\n> grows too large to be 'static inline'.\n>\n> -- Hannes\n>\n\nFixed locally.\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"132054","messageId":"40aa078e1001181433v3c86f147wf3e6aace4501c1a8@mail.gmail.com","threadId":"22235","inReplyTo":"40aa078e1001160112k68c0daafnd6abcb715e1176fe@mail.gmail.com","subject":"Re: [PATCH v2 06/14] mingw: use real pid","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-18T22:33:25Z","receivedAt":"2010-01-18T22:33:25Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Sat, Jan 16, 2010 at 10:12 AM, Erik Faye-Lund\n<kusmabite@googlemail.com> wrote:\n> On Sat, Jan 16, 2010 at 9:03 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n>> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>>> On Fri, Jan 15, 2010 at 11:30 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n>>> > On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>>> >> @@ -729,7 +729,7 @@ static pid_t mingw_spawnve(const char *cmd, const\n>>> >> char **argv, char **env, return -1;\n>>> >>       }\n>>> >>       CloseHandle(pi.hThread);\n>>> >> -     return (pid_t)pi.hProcess;\n>>> >> +     return (pid_t)pi.dwProcessId;\n>>> >>  }\n>>> >\n>>> > You are not using the pi.hProcess anymore, so you must close it.\n>>>\n>>> No. If I do, the pid becomes invalid after the process is finished,\n>>> and waitpid won't work. I couldn't find anywhere were we actually were\n>>> closing the handle, even after it was finished. So I don't think we\n>>> leak any more than we already did (for non-daemon purposes).\n>>\n>> Previously, this handle was closed by _cwait() (it was the \"pid\"), so we\n>> didn't leak it.\n>\n> Oh, I see. My planned route with this (before I looked for where the\n> handle was closed), was to maintain some sort of list of each started\n> PID and their handle, and lookup in that list instead of using\n> OpenProcess. I guess that would solve the problem here, but it feels a\n> bit nasty. Not as nasty as introducing a leak, though.\n>\n\nWhat I had in mind was something along these lines:\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex e2821b3..71201d0 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -638,6 +638,13 @@ static int env_compare(const void *a, const void *b)\n \treturn strcasecmp(*ea, *eb);\n }\n\n+struct pid_info {\n+\tpid_t pid;\n+\tHANDLE proc;\n+};\n+static struct pid_info *pinfo;\n+static int num_pinfo;\n+\n static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,\n \t\t\t   int prepend_cmd)\n {\n@@ -729,6 +736,13 @@ static pid_t mingw_spawnve(const char *cmd, const\nchar **argv, char **env,\n \t\treturn -1;\n \t}\n \tCloseHandle(pi.hThread);\n+\n+\t/* store process handle */\n+\tnum_pinfo++;\n+\tpinfo = xrealloc(pinfo, sizeof(struct pid_info) * num_pinfo);\n+\tpinfo[num_pinfo - 1].pid = pi.dwProcessId;\n+\tpinfo[num_pinfo - 1].proc = pi.hProcess;\n+\n \treturn (pid_t)pi.dwProcessId;\n }\n\n@@ -1536,6 +1550,7 @@ int waitpid(pid_t pid, int *status, unsigned options)\n \t}\n\n \tif (options == 0) {\n+\t\tint i;\n \t\tif (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {\n \t\t\tCloseHandle(h);\n \t\t\treturn 0;\n@@ -1544,6 +1559,19 @@ int waitpid(pid_t pid, int *status, unsigned options)\n \t\tif (status)\n \t\t\tGetExitCodeProcess(h, (LPDWORD)status);\n\n+\t\tfor (i = 0; i < num_pinfo; ++i)\n+\t\t\tif (pinfo[i].pid == pid)\n+\t\t\t\tbreak;\n+\n+\t\tif (i < num_pinfo) {\n+\t\t\tCloseHandle(pinfo[i].proc);\n+\t\t\tmemmove(pinfo + i, pinfo + i + 1,\n+\t\t\t    sizeof(struct pid_info) * (num_pinfo - i - 1));\n+\t\t\tnum_pinfo--;\n+\t\t\tpinfo = xrealloc(pinfo,\n+\t\t\t    sizeof(struct pid_info) * num_pinfo);\n+\t\t}\n+\n \t\tCloseHandle(h);\n \t\treturn pid;\n \t}\n\n\n\n-- \nErik \"kusma\" Faye-Lund\n"},{"id":"132126","messageId":"201001191919.16070.j6t@kdbg.org","threadId":"22235","inReplyTo":"40aa078e1001181433v3c86f147wf3e6aace4501c1a8@mail.gmail.com","subject":"Re: [PATCH v2 06/14] mingw: use real pid","fromName":"Johannes Sixt","fromEmail":"j6t@kdbg.org","sentAt":"2010-01-19T18:19:15Z","receivedAt":"2010-01-19T18:19:15Z","isPatch":true,"sender":{"key":"j6t@kdbg.org","avatar":"https://avatars.githubusercontent.com/u/14810926?v=4"},"body":"On Montag, 18. Januar 2010, Erik Faye-Lund wrote:\n> On Sat, Jan 16, 2010 at 10:12 AM, Erik Faye-Lund wrote:\n> > On Sat, Jan 16, 2010 at 9:03 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n> >> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n> >>> No. If I do, the pid becomes invalid after the process is finished,\n> >>> and waitpid won't work. I couldn't find anywhere were we actually were\n> >>> closing the handle, even after it was finished. So I don't think we\n> >>> leak any more than we already did (for non-daemon purposes).\n> >>\n> >> Previously, this handle was closed by _cwait() (it was the \"pid\"), so we\n> >> didn't leak it.\n> >\n> > Oh, I see. My planned route with this (before I looked for where the\n> > handle was closed), was to maintain some sort of list of each started\n> > PID and their handle, and lookup in that list instead of using\n> > OpenProcess. I guess that would solve the problem here, but it feels a\n> > bit nasty. Not as nasty as introducing a leak, though.\n>\n> What I had in mind was something along these lines:\n\nGiven that that the process ID is the user-visible (and system-wide unique) \nidentifier of a process, this looks like the only reasonable way to go. Your \nimplementation looks good as well.\n\n> +\t/* store process handle */\n\n\t/*\n\t * The process ID is the human-readable identifier of the process\n\t * that we want to present in log and error messages. The handle\n\t * is not useful for this purpose. But we cannot close it, either,\n\t * because it is not possible to turn a process ID into a process\n\t * handle after the process terminated.\n\t * Keep the handle in a list for waitpid.\n\t */\n\n> +\tnum_pinfo++;\n> +\tpinfo = xrealloc(pinfo, sizeof(struct pid_info) * num_pinfo);\n> +\tpinfo[num_pinfo - 1].pid = pi.dwProcessId;\n> +\tpinfo[num_pinfo - 1].proc = pi.hProcess;\n> +\n>  \treturn (pid_t)pi.dwProcessId;\n\n-- Hannes\n"},{"id":"132134","messageId":"40aa078e1001191123t7e8e9a47l46394d62648dfdb8@mail.gmail.com","threadId":"22235","inReplyTo":"201001191919.16070.j6t@kdbg.org","subject":"Re: [PATCH v2 06/14] mingw: use real pid","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@googlemail.com","sentAt":"2010-01-19T19:23:32Z","receivedAt":"2010-01-19T19:23:32Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Tue, Jan 19, 2010 at 7:19 PM, Johannes Sixt <j6t@kdbg.org> wrote:\n> On Montag, 18. Januar 2010, Erik Faye-Lund wrote:\n>> On Sat, Jan 16, 2010 at 10:12 AM, Erik Faye-Lund wrote:\n>> > On Sat, Jan 16, 2010 at 9:03 AM, Johannes Sixt <j6t@kdbg.org> wrote:\n>> >> On Freitag, 15. Januar 2010, Erik Faye-Lund wrote:\n>> >>> No. If I do, the pid becomes invalid after the process is finished,\n>> >>> and waitpid won't work. I couldn't find anywhere were we actually were\n>> >>> closing the handle, even after it was finished. So I don't think we\n>> >>> leak any more than we already did (for non-daemon purposes).\n>> >>\n>> >> Previously, this handle was closed by _cwait() (it was the \"pid\"), so we\n>> >> didn't leak it.\n>> >\n>> > Oh, I see. My planned route with this (before I looked for where the\n>> > handle was closed), was to maintain some sort of list of each started\n>> > PID and their handle, and lookup in that list instead of using\n>> > OpenProcess. I guess that would solve the problem here, but it feels a\n>> > bit nasty. Not as nasty as introducing a leak, though.\n>>\n>> What I had in mind was something along these lines:\n>\n> Given that that the process ID is the user-visible (and system-wide unique)\n> identifier of a process, this looks like the only reasonable way to go. Your\n> implementation looks good as well.\n>\n>> +     /* store process handle */\n>\n>        /*\n>         * The process ID is the human-readable identifier of the process\n>         * that we want to present in log and error messages. The handle\n>         * is not useful for this purpose. But we cannot close it, either,\n>         * because it is not possible to turn a process ID into a process\n>         * handle after the process terminated.\n>         * Keep the handle in a list for waitpid.\n>         */\n>\n\nMuch better, thanks.\n\n-- \nErik \"kusma\" Faye-Lund\n"}]}