{"thread":{"id":"25629","subject":"[PATCH v6 00/16] daemon-win32","startedAt":"2010-11-03T16:31:18Z","lastAt":"2010-11-04T10:15:05Z","messageCount":31,"participants":["Erik Faye-Lund","Pat Thoyts","Martin Storsjö"],"isPatch":true,"patchVersion":6,"patchTotal":16},"messages":[{"id":"155055","messageId":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":null,"subject":"[PATCH v6 00/16] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:18Z","receivedAt":"2010-11-03T16:31:18Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Here's hopefully the last iteration of this series. The previous version\nonly got a single complain about a typo in the subject of patch 14/15, so\nit seems like most controversies have been settled.\n\nThis time the series has been rebased to junio's master branch, as the\n'as/daemon-multi-listen' topic has been merged there.\n\nThe series can also be pulled from the 'win32-daemon-v6' tag in\ngit://repo.or.cz/git/kusma.git\n\nErik Faye-Lund (12):\n  inet_ntop: fix a couple of old-style decls\n  mingw: use real pid\n  mingw: support waitpid with pid > 0 and WNOHANG\n  mingw: add kill emulation\n  daemon: use run-command api for async serving\n  daemon: use full buffered mode for stderr\n  daemon: get remote host address from root-process\n  mingw: import poll-emulation from gnulib\n  mingw: use poll-emulation from gnulib\n  daemon: use socklen_t\n  daemon: make --inetd and --detach incompatible\n  daemon: opt-out on features that require posix\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 Documentation/git-daemon.txt |    3 +-\n Makefile                     |   23 ++-\n compat/inet_ntop.c           |   22 +--\n compat/inet_pton.c           |    8 +-\n compat/mingw.c               |  232 +++++++++++------\n compat/mingw.h               |   41 ++--\n compat/win32/sys/poll.c      |  596 ++++++++++++++++++++++++++++++++++++++++++\n compat/win32/sys/poll.h      |   53 ++++\n compat/win32/syslog.c        |   72 +++++\n compat/win32/syslog.h        |   20 ++\n daemon.c                     |  250 ++++++++++--------\n git-compat-util.h            |   11 +-\n 12 files changed, 1103 insertions(+), 228 deletions(-)\n create mode 100644 compat/win32/sys/poll.c\n create mode 100644 compat/win32/sys/poll.h\n create mode 100644 compat/win32/syslog.c\n create mode 100644 compat/win32/syslog.h\n\n-- \n1.7.3.2.161.gd6e00\n"},{"id":"155057","messageId":"1288801894-1168-2-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 01/16] mingw: add network-wrappers for daemon","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:19Z","receivedAt":"2010-11-03T16:31:19Z","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.\n\nSigned-off-by: Mike Pape <dotzenlabs@gmail.com>\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c |   44 +++++++++++++++++++++++++++++++++++++++++++-\n compat/mingw.h |   16 ++++++++++++++++\n 2 files changed, 59 insertions(+), 1 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 6590f33..701a555 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1175,7 +1175,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@@ -1205,6 +1208,45 @@ 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\tint err = errno;\n+\t\tclosesocket(s2);\n+\t\treturn error(\"unable to make a socket file descriptor: %s\",\n+\t\t\tstrerror(err));\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 83e35e8..a5bde82 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 uid_t;\n+typedef int socklen_t;\n #define hstrerror strerror\n \n #define S_IFLNK    0120000 /* Symbolic link */\n@@ -47,6 +48,9 @@ typedef int uid_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@@ -225,6 +229,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.7.3.2.161.gd6e00\n"},{"id":"155059","messageId":"1288801894-1168-3-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 02/16] mingw: implement syslog","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:20Z","receivedAt":"2010-11-03T16:31: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\nSyslog does not usually exist on Windows, so implement our own using\nWindow's ReportEvent mechanism.\n\nStrings containing \"%1\" gets expanded into them selves by ReportEvent,\nresulting in an unreadable string. \"%2\" and above is not a problem.\nUnfortunately, on Windows an IPv6 address can contain \"%1\", so expand\n\"%1\" to \"% 1\" before reporting. \"%%1\" is also a problem for ReportEvent,\nbut that string cannot occur in an IPv6 address.\n\nSigned-off-by: Mike Pape <dotzenlabs@gmail.com>\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n Makefile              |    5 ++-\n compat/win32/syslog.c |   72 +++++++++++++++++++++++++++++++++++++++++++++++++\n compat/win32/syslog.h |   20 +++++++++++++\n daemon.c              |    2 -\n git-compat-util.h     |    1 +\n 5 files changed, 96 insertions(+), 4 deletions(-)\n create mode 100644 compat/win32/syslog.c\n create mode 100644 compat/win32/syslog.h\n\ndiff --git a/Makefile b/Makefile\nindex 1f1ce04..d9d9419 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -496,6 +496,7 @@ LIB_H += compat/bswap.h\n LIB_H += compat/cygwin.h\n LIB_H += compat/mingw.h\n LIB_H += compat/win32/pthread.h\n+LIB_H += compat/win32/syslog.h\n LIB_H += csum-file.h\n LIB_H += decorate.h\n LIB_H += delta.h\n@@ -1081,7 +1082,7 @@ ifeq ($(uname_S),Windows)\n \tAR = compat/vcbuild/scripts/lib.pl\n \tCFLAGS =\n \tBASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE\n-\tCOMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o\n+\tCOMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o compat/win32/syslog.o\n \tCOMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\\\".exe\\\"\n \tBASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib\n \tEXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib\n@@ -1131,7 +1132,7 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \\\n-\t\tcompat/win32/pthread.o\n+\t\tcompat/win32/pthread.o compat/win32/syslog.o\n \tEXTLIBS += -lws2_32\n \tPTHREAD_LIBS =\n \tX = .exe\ndiff --git a/compat/win32/syslog.c b/compat/win32/syslog.c\nnew file mode 100644\nindex 0000000..42b95a9\n--- /dev/null\n+++ b/compat/win32/syslog.c\n@@ -0,0 +1,72 @@\n+#include \"../../git-compat-util.h\"\n+#include \"../../strbuf.h\"\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+\n+\tms_eventlog = RegisterEventSourceA(NULL, ident);\n+\n+\tif (!ms_eventlog)\n+\t\twarning(\"RegisterEventSource() failed: %lu\", GetLastError());\n+}\n+\n+void syslog(int priority, const char *fmt, ...)\n+{\n+\tstruct strbuf sb = STRBUF_INIT;\n+\tstruct strbuf_expand_dict_entry dict[] = {\n+\t\t{\"1\", \"% 1\"},\n+\t\t{NULL, NULL}\n+\t};\n+\tWORD logtype;\n+\tchar *str;\n+\tint str_len;\n+\tva_list ap;\n+\n+\tif (!ms_eventlog)\n+\t\treturn;\n+\n+\tva_start(ap, fmt);\n+\tstr_len = vsnprintf(NULL, 0, fmt, ap);\n+\tva_end(ap);\n+\n+\tif (str_len < 0) {\n+\t\twarning(\"vsnprintf failed: '%s'\", strerror(errno));\n+\t\treturn;\n+\t}\n+\n+\tstr = malloc(str_len + 1);\n+\tva_start(ap, fmt);\n+\tvsnprintf(str, str_len + 1, fmt, ap);\n+\tva_end(ap);\n+\tstrbuf_expand(&sb, str, strbuf_expand_dict_cb, &dict);\n+\tfree(str);\n+\n+\tswitch (priority) {\n+\tcase LOG_EMERG:\n+\tcase LOG_ALERT:\n+\tcase LOG_CRIT:\n+\tcase LOG_ERR:\n+\t\tlogtype = EVENTLOG_ERROR_TYPE;\n+\t\tbreak;\n+\n+\tcase LOG_WARNING:\n+\t\tlogtype = EVENTLOG_WARNING_TYPE;\n+\t\tbreak;\n+\n+\tcase LOG_NOTICE:\n+\tcase LOG_INFO:\n+\tcase LOG_DEBUG:\n+\tdefault:\n+\t\tlogtype = EVENTLOG_INFORMATION_TYPE;\n+\t\tbreak;\n+\t}\n+\n+\tReportEventA(ms_eventlog, logtype, 0, 0, NULL, 1, 0,\n+\t    (const char **)&sb.buf, NULL);\n+\n+\tstrbuf_release(&sb);\n+}\ndiff --git a/compat/win32/syslog.h b/compat/win32/syslog.h\nnew file mode 100644\nindex 0000000..70daa7c\n--- /dev/null\n+++ b/compat/win32/syslog.h\n@@ -0,0 +1,20 @@\n+#ifndef SYSLOG_H\n+#define SYSLOG_H\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+void openlog(const char *ident, int logopt, int facility);\n+void syslog(int priority, const char *fmt, ...);\n+\n+#endif /* SYSLOG_H */\ndiff --git a/daemon.c b/daemon.c\nindex 7ccd097..535ae88 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -5,8 +5,6 @@\n #include \"strbuf.h\"\n #include \"string-list.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 2af8d3e..e192831 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -104,6 +104,7 @@\n #include <assert.h>\n #include <regex.h>\n #include <utime.h>\n+#include <syslog.h>\n #ifndef __MINGW32__\n #include <sys/wait.h>\n #include <sys/poll.h>\n-- \n1.7.3.2.161.gd6e00\n"},{"id":"155058","messageId":"1288801894-1168-4-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 03/16] compat: add inet_pton and inet_ntop prototypes","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:21Z","receivedAt":"2010-11-03T16:31: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\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 d9d9419..2aa067a 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -1398,9 +1398,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 e192831..56dce85 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -387,6 +387,14 @@ static inline void *gitmempcpy(void *dest, const void *src, size_t n)\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 typedef void (*try_to_free_t)(size_t);\n-- \n1.7.3.2.161.gd6e00\n"},{"id":"155060","messageId":"1288801894-1168-5-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 04/16] inet_ntop: fix a couple of old-style decls","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:22Z","receivedAt":"2010-11-03T16:31:22Z","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.7.3.2.161.gd6e00\n"},{"id":"155070","messageId":"1288801894-1168-6-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 05/16] mingw: use real pid","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:23Z","receivedAt":"2010-11-03T16:31:23Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"The Windows port have so far been using process handles in place\nof PID. However, this is not work consistent with what getpid\nreturns.\n\nPIDs are system-global identifiers, but process handles are local\nto a process. Using PIDs instead of process handles allows, for\ninstance, a user to kill a hung process with the Task Manager,\nsomething that would have been impossible with process handles.\n\nChange the code to use the real PID, and use OpenProcess to get a\nprocess-handle. Store the PID and the process handle in a table\nprotected by a critical section, so we can safely close the\nprocess handle later.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/mingw.c |   70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++-\n compat/mingw.h |   10 ++-----\n 2 files changed, 72 insertions(+), 8 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex 701a555..e2e3c54 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -702,6 +702,13 @@ static int env_compare(const void *a, const void *b)\n \treturn strcasecmp(*ea, *eb);\n }\n \n+struct {\n+\tpid_t pid;\n+\tHANDLE proc;\n+} *pinfo;\n+static int num_pinfo;\n+CRITICAL_SECTION pinfo_cs;\n+\n static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,\n \t\t\t      const char *dir,\n \t\t\t      int prepend_cmd, int fhin, int fhout, int fherr)\n@@ -794,7 +801,23 @@ static pid_t mingw_spawnve_fd(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+\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+\tEnterCriticalSection(&pinfo_cs);\n+\tnum_pinfo++;\n+\tpinfo = xrealloc(pinfo, sizeof(*pinfo) * num_pinfo);\n+\tpinfo[num_pinfo - 1].pid = pi.dwProcessId;\n+\tpinfo[num_pinfo - 1].proc = pi.hProcess;\n+\tLeaveCriticalSection(&pinfo_cs);\n+\n+\treturn (pid_t)pi.dwProcessId;\n }\n \n static pid_t mingw_spawnve(const char *cmd, const char **argv, char **env,\n@@ -1518,6 +1541,51 @@ char *getpass(const char *prompt)\n \treturn strbuf_detach(&buf, NULL);\n }\n \n+pid_t waitpid(pid_t pid, int *status, unsigned options)\n+{\n+\tHANDLE h = OpenProcess(SYNCHRONIZE | PROCESS_QUERY_INFORMATION,\n+\t    FALSE, pid);\n+\tif (!h) {\n+\t\terrno = ECHILD;\n+\t\treturn -1;\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+\t\t}\n+\n+\t\tif (status)\n+\t\t\tGetExitCodeProcess(h, (LPDWORD)status);\n+\n+\t\tEnterCriticalSection(&pinfo_cs);\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(*pinfo) * (num_pinfo - i - 1));\n+\t\t\tnum_pinfo--;\n+\t\t\tpinfo = xrealloc(pinfo,\n+\t\t\t    sizeof(*pinfo) * num_pinfo);\n+\t\t}\n+\n+\t\tLeaveCriticalSection(&pinfo_cs);\n+\n+\t\tCloseHandle(h);\n+\t\treturn pid;\n+\t}\n+\tCloseHandle(h);\n+\n+\terrno = EINVAL;\n+\treturn -1;\n+}\n+\n #ifndef NO_MINGW_REPLACE_READDIR\n /* MinGW readdir implementation to avoid extra lstats for Git */\n struct mingw_DIR\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex a5bde82..7c4eeea 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -140,13 +140,7 @@ static inline int mingw_unlink(const char *pathname)\n }\n #define unlink mingw_unlink\n \n-static inline pid_t waitpid(pid_t pid, int *status, unsigned options)\n-{\n-\tif (options == 0)\n-\t\treturn _cwait(status, pid, 0);\n-\terrno = EINVAL;\n-\treturn -1;\n-}\n+pid_t waitpid(pid_t pid, int *status, unsigned options);\n \n #ifndef NO_OPENSSL\n #include <openssl/ssl.h>\n@@ -321,11 +315,13 @@ void free_environ(char **env);\n static int mingw_main(); \\\n int main(int argc, const char **argv) \\\n { \\\n+\textern CRITICAL_SECTION pinfo_cs; \\\n \t_fmode = _O_BINARY; \\\n \t_setmode(_fileno(stdin), _O_BINARY); \\\n \t_setmode(_fileno(stdout), _O_BINARY); \\\n \t_setmode(_fileno(stderr), _O_BINARY); \\\n \targv[0] = xstrdup(_pgmptr); \\\n+\tInitializeCriticalSection(&pinfo_cs); \\\n \treturn mingw_main(argc, argv); \\\n } \\\n static int mingw_main(c,v)\n-- \n1.7.3.2.161.gd6e00\n"},{"id":"155056","messageId":"1288801894-1168-7-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 06/16] mingw: support waitpid with pid > 0 and WNOHANG","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:24Z","receivedAt":"2010-11-03T16:31: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.c |    6 ++++++\n compat/mingw.h |    1 +\n 2 files changed, 7 insertions(+), 0 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex e2e3c54..2e7c644 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1550,6 +1550,12 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n \t\treturn -1;\n \t}\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\tint i;\n \t\tif (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 7c4eeea..379d7bf 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -140,6 +140,7 @@ static inline int mingw_unlink(const char *pathname)\n }\n #define unlink mingw_unlink\n \n+#define WNOHANG 1\n pid_t waitpid(pid_t pid, int *status, unsigned options);\n \n #ifndef NO_OPENSSL\n-- \n1.7.3.2.161.gd6e00\n"},{"id":"155066","messageId":"1288801894-1168-8-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 07/16] mingw: add kill emulation","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:25Z","receivedAt":"2010-11-03T16:31:25Z","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 2e7c644..21d1c2c 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -932,6 +932,25 @@ void mingw_execv(const char *cmd, char *const *argv)\n \tmingw_execve(cmd, argv, environ);\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\terrno = err_win_to_posix(GetLastError());\n+\t\tCloseHandle(h);\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 379d7bf..51fca2f 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -143,6 +143,9 @@ static inline int mingw_unlink(const char *pathname)\n #define WNOHANG 1\n pid_t waitpid(pid_t pid, int *status, unsigned options);\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.7.3.2.161.gd6e00\n"},{"id":"155067","messageId":"1288801894-1168-9-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 08/16] daemon: use run-command api for async serving","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:26Z","receivedAt":"2010-11-03T16:31:26Z","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.\n\nInstead we invent the flag --serve, which is a stripped down\nversion of --inetd-mode. We use start_command() to call\ngit-daemon with this flag appended to serve clients.\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 535ae88..6eee570 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -614,17 +614,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@@ -633,19 +633,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@@ -661,7 +648,7 @@ static void kill_some_child(void)\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@@ -671,18 +658,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+static char **cld_argv;\n static void handle(int incoming, struct sockaddr *addr, int addrlen)\n {\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@@ -695,22 +690,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-\tdup2(incoming, 0);\n-\tdup2(incoming, 1);\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-\texit(execute(addr));\n }\n \n static void child_handler(int signo)\n@@ -991,7 +979,7 @@ int main(int argc, char **argv)\n {\n \tint listen_port = 0;\n \tstruct string_list listen_addr = STRING_LIST_INIT_NODUP;\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@@ -1017,6 +1005,10 @@ 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\tinetd_mode = 1;\n \t\t\tlog_syslog = 1;\n@@ -1162,13 +1154,15 @@ int main(int argc, char **argv)\n \t\t    base_path);\n \n \tif (inetd_mode) {\n+\t\tif (!freopen(\"/dev/null\", \"w\", stderr))\n+\t\t\tdie_errno(\"failed to redirect stderr to /dev/null\");\n+\t}\n+\n+\tif (inetd_mode || serve_mode) {\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\t\tdie_errno(\"failed to redirect stderr to /dev/null\");\n-\n \t\tif (getpeername(0, peer, &slen))\n \t\t\tpeer = NULL;\n \n@@ -1185,5 +1179,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.7.3.2.161.gd6e00\n"},{"id":"155068","messageId":"1288801894-1168-10-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 09/16] daemon: use full buffered mode for stderr","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:27Z","receivedAt":"2010-11-03T16:31:27Z","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 6eee570..9a4884a 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -67,12 +67,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@@ -1117,7 +1119,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.7.3.2.161.gd6e00\n"},{"id":"155069","messageId":"1288801894-1168-11-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 10/16] Improve the mingw getaddrinfo stub to handle more use cases","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:28Z","receivedAt":"2010-11-03T16:31:28Z","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 21d1c2c..d88c0d0 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1035,19 +1035,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@@ -1059,14 +1062,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.7.3.2.161.gd6e00\n"},{"id":"155064","messageId":"1288801894-1168-12-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 11/16] daemon: get remote host address from root-process","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:29Z","receivedAt":"2010-11-03T16:31:29Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Get remote host in the process that accept() and pass it through\nthe REMOTE_ADDR environment variable to the handler-process.\nIntroduce the REMOTE_PORT environmen variable for the port.\n\nUse these variables for reporting instead of doing\ngetpeername(0, ...), which doesn't work on Windows.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n daemon.c |   67 +++++++++++++++++++++++++++----------------------------------\n 1 files changed, 30 insertions(+), 37 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 9a4884a..3d8f6e6 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -516,37 +516,14 @@ static void parse_host_arg(char *extra_args, int buflen)\n }\n \n \n-static int execute(struct sockaddr *addr)\n+static int execute(void)\n {\n \tstatic char line[1000];\n \tint pktlen, len, i;\n+\tchar *addr = getenv(\"REMOTE_ADDR\"), *port = getenv(\"REMOTE_PORT\");\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+\tif (addr)\n+\t\tloginfo(\"Connection from %s:%s\", addr, port);\n \n \talarm(init_timeout ? init_timeout : timeout);\n \tpktlen = packet_read_line(0, line, sizeof(line));\n@@ -680,6 +657,8 @@ static char **cld_argv;\n static void handle(int incoming, struct sockaddr *addr, int addrlen)\n {\n \tstruct child_process cld = { 0 };\n+\tchar addrbuf[300] = \"REMOTE_ADDR=\", portbuf[300];\n+\tchar *env[] = { addrbuf, portbuf, NULL };\n \n \tif (max_connections && live_children >= max_connections) {\n \t\tkill_some_child();\n@@ -692,6 +671,28 @@ static void handle(int incoming, struct sockaddr *addr, int addrlen)\n \t\t}\n \t}\n \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 + 12,\n+\t\t    sizeof(addrbuf) - 12);\n+\t\tsnprintf(portbuf, sizeof(portbuf), \"REMOTE_PORT=%d\",\n+\t\t    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 + 12;\n+\t\t*buf++ = '['; *buf = '\\0'; /* stpcpy() is cool */\n+\t\tinet_ntop(AF_INET6, &sin6_addr->sin6_addr, buf,\n+\t\t    sizeof(addrbuf) - 13);\n+\t\tstrcat(buf, \"]\");\n+\n+\t\tsnprintf(portbuf, sizeof(portbuf), \"REMOTE_PORT=%d\",\n+\t\t    ntohs(sin6_addr->sin6_port));\n+#endif\n+\t}\n+\n+\tcld.env = (const char **)env;\n \tcld.argv = (const char **)cld_argv;\n \tcld.in = incoming;\n \tcld.out = dup(incoming);\n@@ -1160,16 +1161,8 @@ int main(int argc, char **argv)\n \t\t\tdie_errno(\"failed to redirect stderr to /dev/null\");\n \t}\n \n-\tif (inetd_mode || serve_mode) {\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 (getpeername(0, peer, &slen))\n-\t\t\tpeer = NULL;\n-\n-\t\treturn execute(peer);\n-\t}\n+\tif (inetd_mode || serve_mode)\n+\t\treturn execute();\n \n \tif (detach) {\n \t\tdaemonize();\n-- \n1.7.3.2.161.gd6e00\n"},{"id":"155065","messageId":"1288801894-1168-13-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 12/16] mingw: import poll-emulation from gnulib","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:30Z","receivedAt":"2010-11-03T16:31:30Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"copy lib/poll.c and lib/poll.in.h verbatim from commit 0a05120 in\ngit://git.savannah.gnu.org/gnulib.git to compat/win32/sys/poll.[ch]\n\nTo upgrade this code in the future, branch out from this commit, copy\nnew versions of the files above on top, and merge back the result.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n compat/win32/sys/poll.c |  597 +++++++++++++++++++++++++++++++++++++++++++++++\n compat/win32/sys/poll.h |   53 +++++\n 2 files changed, 650 insertions(+), 0 deletions(-)\n create mode 100644 compat/win32/sys/poll.c\n create mode 100644 compat/win32/sys/poll.h\n\ndiff --git a/compat/win32/sys/poll.c b/compat/win32/sys/poll.c\nnew file mode 100644\nindex 0000000..7c52cb6\n--- /dev/null\n+++ b/compat/win32/sys/poll.c\n@@ -0,0 +1,597 @@\n+/* Emulation for poll(2)\n+   Contributed by Paolo Bonzini.\n+\n+   Copyright 2001-2003, 2006-2010 Free Software Foundation, Inc.\n+\n+   This file is part of gnulib.\n+\n+   This program is free software; you can redistribute it and/or modify\n+   it under the terms of the GNU General Public License as published by\n+   the Free Software Foundation; either version 2, or (at your option)\n+   any later version.\n+\n+   This program is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+   GNU General Public License for more details.\n+\n+   You should have received a copy of the GNU General Public License along\n+   with this program; if not, write to the Free Software Foundation,\n+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */\n+\n+/* Tell gcc not to warn about the (nfd < 0) tests, below.  */\n+#if (__GNUC__ == 4 && 3 <= __GNUC_MINOR__) || 4 < __GNUC__\n+# pragma GCC diagnostic ignored \"-Wtype-limits\"\n+#endif\n+\n+#include <config.h>\n+#include <alloca.h>\n+\n+#include <sys/types.h>\n+#include \"poll.h\"\n+#include <errno.h>\n+#include <limits.h>\n+#include <assert.h>\n+\n+#if (defined _WIN32 || defined __WIN32__) && ! defined __CYGWIN__\n+# define WIN32_NATIVE\n+# include <winsock2.h>\n+# include <windows.h>\n+# include <io.h>\n+# include <stdio.h>\n+# include <conio.h>\n+#else\n+# include <sys/time.h>\n+# include <sys/socket.h>\n+# include <sys/select.h>\n+# include <unistd.h>\n+#endif\n+\n+#ifdef HAVE_SYS_IOCTL_H\n+# include <sys/ioctl.h>\n+#endif\n+#ifdef HAVE_SYS_FILIO_H\n+# include <sys/filio.h>\n+#endif\n+\n+#include <time.h>\n+\n+#ifndef INFTIM\n+# define INFTIM (-1)\n+#endif\n+\n+/* BeOS does not have MSG_PEEK.  */\n+#ifndef MSG_PEEK\n+# define MSG_PEEK 0\n+#endif\n+\n+#ifdef WIN32_NATIVE\n+\n+#define IsConsoleHandle(h) (((long) (h) & 3) == 3)\n+\n+static BOOL\n+IsSocketHandle (HANDLE h)\n+{\n+  WSANETWORKEVENTS ev;\n+\n+  if (IsConsoleHandle (h))\n+    return FALSE;\n+\n+  /* Under Wine, it seems that getsockopt returns 0 for pipes too.\n+     WSAEnumNetworkEvents instead distinguishes the two correctly.  */\n+  ev.lNetworkEvents = 0xDEADBEEF;\n+  WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);\n+  return ev.lNetworkEvents != 0xDEADBEEF;\n+}\n+\n+/* Declare data structures for ntdll functions.  */\n+typedef struct _FILE_PIPE_LOCAL_INFORMATION {\n+  ULONG NamedPipeType;\n+  ULONG NamedPipeConfiguration;\n+  ULONG MaximumInstances;\n+  ULONG CurrentInstances;\n+  ULONG InboundQuota;\n+  ULONG ReadDataAvailable;\n+  ULONG OutboundQuota;\n+  ULONG WriteQuotaAvailable;\n+  ULONG NamedPipeState;\n+  ULONG NamedPipeEnd;\n+} FILE_PIPE_LOCAL_INFORMATION, *PFILE_PIPE_LOCAL_INFORMATION;\n+\n+typedef struct _IO_STATUS_BLOCK\n+{\n+  union {\n+    DWORD Status;\n+    PVOID Pointer;\n+  } u;\n+  ULONG_PTR Information;\n+} IO_STATUS_BLOCK, *PIO_STATUS_BLOCK;\n+\n+typedef enum _FILE_INFORMATION_CLASS {\n+  FilePipeLocalInformation = 24\n+} FILE_INFORMATION_CLASS, *PFILE_INFORMATION_CLASS;\n+\n+typedef DWORD (WINAPI *PNtQueryInformationFile)\n+         (HANDLE, IO_STATUS_BLOCK *, VOID *, ULONG, FILE_INFORMATION_CLASS);\n+\n+# ifndef PIPE_BUF\n+#  define PIPE_BUF      512\n+# endif\n+\n+/* Compute revents values for file handle H.  If some events cannot happen\n+   for the handle, eliminate them from *P_SOUGHT.  */\n+\n+static int\n+win32_compute_revents (HANDLE h, int *p_sought)\n+{\n+  int i, ret, happened;\n+  INPUT_RECORD *irbuffer;\n+  DWORD avail, nbuffer;\n+  BOOL bRet;\n+  IO_STATUS_BLOCK iosb;\n+  FILE_PIPE_LOCAL_INFORMATION fpli;\n+  static PNtQueryInformationFile NtQueryInformationFile;\n+  static BOOL once_only;\n+\n+  switch (GetFileType (h))\n+    {\n+    case FILE_TYPE_PIPE:\n+      if (!once_only)\n+        {\n+          NtQueryInformationFile = (PNtQueryInformationFile)\n+            GetProcAddress (GetModuleHandle (\"ntdll.dll\"),\n+                            \"NtQueryInformationFile\");\n+          once_only = TRUE;\n+        }\n+\n+      happened = 0;\n+      if (PeekNamedPipe (h, NULL, 0, NULL, &avail, NULL) != 0)\n+        {\n+          if (avail)\n+            happened |= *p_sought & (POLLIN | POLLRDNORM);\n+        }\n+      else if (GetLastError () == ERROR_BROKEN_PIPE)\n+        happened |= POLLHUP;\n+\n+      else\n+        {\n+          /* It was the write-end of the pipe.  Check if it is writable.\n+             If NtQueryInformationFile fails, optimistically assume the pipe is\n+             writable.  This could happen on Win9x, where NtQueryInformationFile\n+             is not available, or if we inherit a pipe that doesn't permit\n+             FILE_READ_ATTRIBUTES access on the write end (I think this should\n+             not happen since WinXP SP2; WINE seems fine too).  Otherwise,\n+             ensure that enough space is available for atomic writes.  */\n+          memset (&iosb, 0, sizeof (iosb));\n+          memset (&fpli, 0, sizeof (fpli));\n+\n+          if (!NtQueryInformationFile\n+              || NtQueryInformationFile (h, &iosb, &fpli, sizeof (fpli),\n+                                         FilePipeLocalInformation)\n+              || fpli.WriteQuotaAvailable >= PIPE_BUF\n+              || (fpli.OutboundQuota < PIPE_BUF &&\n+                  fpli.WriteQuotaAvailable == fpli.OutboundQuota))\n+            happened |= *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);\n+        }\n+      return happened;\n+\n+    case FILE_TYPE_CHAR:\n+      ret = WaitForSingleObject (h, 0);\n+      if (!IsConsoleHandle (h))\n+        return ret == WAIT_OBJECT_0 ? *p_sought & ~(POLLPRI | POLLRDBAND) : 0;\n+\n+      nbuffer = avail = 0;\n+      bRet = GetNumberOfConsoleInputEvents (h, &nbuffer);\n+      if (bRet)\n+        {\n+          /* Input buffer.  */\n+          *p_sought &= POLLIN | POLLRDNORM;\n+          if (nbuffer == 0)\n+            return POLLHUP;\n+          if (!*p_sought)\n+            return 0;\n+\n+          irbuffer = (INPUT_RECORD *) alloca (nbuffer * sizeof (INPUT_RECORD));\n+          bRet = PeekConsoleInput (h, irbuffer, nbuffer, &avail);\n+          if (!bRet || avail == 0)\n+            return POLLHUP;\n+\n+          for (i = 0; i < avail; i++)\n+            if (irbuffer[i].EventType == KEY_EVENT)\n+              return *p_sought;\n+          return 0;\n+        }\n+      else\n+        {\n+          /* Screen buffer.  */\n+          *p_sought &= POLLOUT | POLLWRNORM | POLLWRBAND;\n+          return *p_sought;\n+        }\n+\n+    default:\n+      ret = WaitForSingleObject (h, 0);\n+      if (ret == WAIT_OBJECT_0)\n+        return *p_sought & ~(POLLPRI | POLLRDBAND);\n+\n+      return *p_sought & (POLLOUT | POLLWRNORM | POLLWRBAND);\n+    }\n+}\n+\n+/* Convert fd_sets returned by select into revents values.  */\n+\n+static int\n+win32_compute_revents_socket (SOCKET h, int sought, long lNetworkEvents)\n+{\n+  int happened = 0;\n+\n+  if ((lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE)) == FD_ACCEPT)\n+    happened |= (POLLIN | POLLRDNORM) & sought;\n+\n+  else if (lNetworkEvents & (FD_READ | FD_ACCEPT | FD_CLOSE))\n+    {\n+      int r, error;\n+\n+      char data[64];\n+      WSASetLastError (0);\n+      r = recv (h, data, sizeof (data), MSG_PEEK);\n+      error = WSAGetLastError ();\n+      WSASetLastError (0);\n+\n+      if (r > 0 || error == WSAENOTCONN)\n+        happened |= (POLLIN | POLLRDNORM) & sought;\n+\n+      /* Distinguish hung-up sockets from other errors.  */\n+      else if (r == 0 || error == WSAESHUTDOWN || error == WSAECONNRESET\n+               || error == WSAECONNABORTED || error == WSAENETRESET)\n+        happened |= POLLHUP;\n+\n+      else\n+        happened |= POLLERR;\n+    }\n+\n+  if (lNetworkEvents & (FD_WRITE | FD_CONNECT))\n+    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;\n+\n+  if (lNetworkEvents & FD_OOB)\n+    happened |= (POLLPRI | POLLRDBAND) & sought;\n+\n+  return happened;\n+}\n+\n+#else /* !MinGW */\n+\n+/* Convert select(2) returned fd_sets into poll(2) revents values.  */\n+static int\n+compute_revents (int fd, int sought, fd_set *rfds, fd_set *wfds, fd_set *efds)\n+{\n+  int happened = 0;\n+  if (FD_ISSET (fd, rfds))\n+    {\n+      int r;\n+      int socket_errno;\n+\n+# if defined __MACH__ && defined __APPLE__\n+      /* There is a bug in Mac OS X that causes it to ignore MSG_PEEK\n+         for some kinds of descriptors.  Detect if this descriptor is a\n+         connected socket, a server socket, or something else using a\n+         0-byte recv, and use ioctl(2) to detect POLLHUP.  */\n+      r = recv (fd, NULL, 0, MSG_PEEK);\n+      socket_errno = (r < 0) ? errno : 0;\n+      if (r == 0 || socket_errno == ENOTSOCK)\n+        ioctl (fd, FIONREAD, &r);\n+# else\n+      char data[64];\n+      r = recv (fd, data, sizeof (data), MSG_PEEK);\n+      socket_errno = (r < 0) ? errno : 0;\n+# endif\n+      if (r == 0)\n+        happened |= POLLHUP;\n+\n+      /* If the event happened on an unconnected server socket,\n+         that's fine. */\n+      else if (r > 0 || ( /* (r == -1) && */ socket_errno == ENOTCONN))\n+        happened |= (POLLIN | POLLRDNORM) & sought;\n+\n+      /* Distinguish hung-up sockets from other errors.  */\n+      else if (socket_errno == ESHUTDOWN || socket_errno == ECONNRESET\n+               || socket_errno == ECONNABORTED || socket_errno == ENETRESET)\n+        happened |= POLLHUP;\n+\n+      else\n+        happened |= POLLERR;\n+    }\n+\n+  if (FD_ISSET (fd, wfds))\n+    happened |= (POLLOUT | POLLWRNORM | POLLWRBAND) & sought;\n+\n+  if (FD_ISSET (fd, efds))\n+    happened |= (POLLPRI | POLLRDBAND) & sought;\n+\n+  return happened;\n+}\n+#endif /* !MinGW */\n+\n+int\n+poll (pfd, nfd, timeout)\n+     struct pollfd *pfd;\n+     nfds_t nfd;\n+     int timeout;\n+{\n+#ifndef WIN32_NATIVE\n+  fd_set rfds, wfds, efds;\n+  struct timeval tv;\n+  struct timeval *ptv;\n+  int maxfd, rc;\n+  nfds_t i;\n+\n+# ifdef _SC_OPEN_MAX\n+  static int sc_open_max = -1;\n+\n+  if (nfd < 0\n+      || (nfd > sc_open_max\n+          && (sc_open_max != -1\n+              || nfd > (sc_open_max = sysconf (_SC_OPEN_MAX)))))\n+    {\n+      errno = EINVAL;\n+      return -1;\n+    }\n+# else /* !_SC_OPEN_MAX */\n+#  ifdef OPEN_MAX\n+  if (nfd < 0 || nfd > OPEN_MAX)\n+    {\n+      errno = EINVAL;\n+      return -1;\n+    }\n+#  endif /* OPEN_MAX -- else, no check is needed */\n+# endif /* !_SC_OPEN_MAX */\n+\n+  /* EFAULT is not necessary to implement, but let's do it in the\n+     simplest case. */\n+  if (!pfd)\n+    {\n+      errno = EFAULT;\n+      return -1;\n+    }\n+\n+  /* convert timeout number into a timeval structure */\n+  if (timeout == 0)\n+    {\n+      ptv = &tv;\n+      ptv->tv_sec = 0;\n+      ptv->tv_usec = 0;\n+    }\n+  else if (timeout > 0)\n+    {\n+      ptv = &tv;\n+      ptv->tv_sec = timeout / 1000;\n+      ptv->tv_usec = (timeout % 1000) * 1000;\n+    }\n+  else if (timeout == INFTIM)\n+    /* wait forever */\n+    ptv = NULL;\n+  else\n+    {\n+      errno = EINVAL;\n+      return -1;\n+    }\n+\n+  /* create fd sets and determine max fd */\n+  maxfd = -1;\n+  FD_ZERO (&rfds);\n+  FD_ZERO (&wfds);\n+  FD_ZERO (&efds);\n+  for (i = 0; i < nfd; i++)\n+    {\n+      if (pfd[i].fd < 0)\n+        continue;\n+\n+      if (pfd[i].events & (POLLIN | POLLRDNORM))\n+        FD_SET (pfd[i].fd, &rfds);\n+\n+      /* see select(2): \"the only exceptional condition detectable\n+         is out-of-band data received on a socket\", hence we push\n+         POLLWRBAND events onto wfds instead of efds. */\n+      if (pfd[i].events & (POLLOUT | POLLWRNORM | POLLWRBAND))\n+        FD_SET (pfd[i].fd, &wfds);\n+      if (pfd[i].events & (POLLPRI | POLLRDBAND))\n+        FD_SET (pfd[i].fd, &efds);\n+      if (pfd[i].fd >= maxfd\n+          && (pfd[i].events & (POLLIN | POLLOUT | POLLPRI\n+                               | POLLRDNORM | POLLRDBAND\n+                               | POLLWRNORM | POLLWRBAND)))\n+        {\n+          maxfd = pfd[i].fd;\n+          if (maxfd > FD_SETSIZE)\n+            {\n+              errno = EOVERFLOW;\n+              return -1;\n+            }\n+        }\n+    }\n+\n+  /* examine fd sets */\n+  rc = select (maxfd + 1, &rfds, &wfds, &efds, ptv);\n+  if (rc < 0)\n+    return rc;\n+\n+  /* establish results */\n+  rc = 0;\n+  for (i = 0; i < nfd; i++)\n+    if (pfd[i].fd < 0)\n+      pfd[i].revents = 0;\n+    else\n+      {\n+        int happened = compute_revents (pfd[i].fd, pfd[i].events,\n+                                        &rfds, &wfds, &efds);\n+        if (happened)\n+          {\n+            pfd[i].revents = happened;\n+            rc++;\n+          }\n+      }\n+\n+  return rc;\n+#else\n+  static struct timeval tv0;\n+  static HANDLE hEvent;\n+  WSANETWORKEVENTS ev;\n+  HANDLE h, handle_array[FD_SETSIZE + 2];\n+  DWORD ret, wait_timeout, nhandles;\n+  fd_set rfds, wfds, xfds;\n+  BOOL poll_again;\n+  MSG msg;\n+  int rc = 0;\n+  nfds_t i;\n+\n+  if (nfd < 0 || timeout < -1)\n+    {\n+      errno = EINVAL;\n+      return -1;\n+    }\n+\n+  if (!hEvent)\n+    hEvent = CreateEvent (NULL, FALSE, FALSE, NULL);\n+\n+  handle_array[0] = hEvent;\n+  nhandles = 1;\n+  FD_ZERO (&rfds);\n+  FD_ZERO (&wfds);\n+  FD_ZERO (&xfds);\n+\n+  /* Classify socket handles and create fd sets. */\n+  for (i = 0; i < nfd; i++)\n+    {\n+      int sought = pfd[i].events;\n+      pfd[i].revents = 0;\n+      if (pfd[i].fd < 0)\n+        continue;\n+      if (!(sought & (POLLIN | POLLRDNORM | POLLOUT | POLLWRNORM | POLLWRBAND\n+                      | POLLPRI | POLLRDBAND)))\n+        continue;\n+\n+      h = (HANDLE) _get_osfhandle (pfd[i].fd);\n+      assert (h != NULL);\n+      if (IsSocketHandle (h))\n+        {\n+          int requested = FD_CLOSE;\n+\n+          /* see above; socket handles are mapped onto select.  */\n+          if (sought & (POLLIN | POLLRDNORM))\n+            {\n+              requested |= FD_READ | FD_ACCEPT;\n+              FD_SET ((SOCKET) h, &rfds);\n+            }\n+          if (sought & (POLLOUT | POLLWRNORM | POLLWRBAND))\n+            {\n+              requested |= FD_WRITE | FD_CONNECT;\n+              FD_SET ((SOCKET) h, &wfds);\n+            }\n+          if (sought & (POLLPRI | POLLRDBAND))\n+            {\n+              requested |= FD_OOB;\n+              FD_SET ((SOCKET) h, &xfds);\n+            }\n+\n+          if (requested)\n+            WSAEventSelect ((SOCKET) h, hEvent, requested);\n+        }\n+      else\n+        {\n+          /* Poll now.  If we get an event, do not poll again.  Also,\n+             screen buffer handles are waitable, and they'll block until\n+             a character is available.  win32_compute_revents eliminates\n+             bits for the \"wrong\" direction. */\n+          pfd[i].revents = win32_compute_revents (h, &sought);\n+          if (sought)\n+            handle_array[nhandles++] = h;\n+          if (pfd[i].revents)\n+            timeout = 0;\n+        }\n+    }\n+\n+  if (select (0, &rfds, &wfds, &xfds, &tv0) > 0)\n+    {\n+      /* Do MsgWaitForMultipleObjects anyway to dispatch messages, but\n+         no need to call select again.  */\n+      poll_again = FALSE;\n+      wait_timeout = 0;\n+    }\n+  else\n+    {\n+      poll_again = TRUE;\n+      if (timeout == INFTIM)\n+        wait_timeout = INFINITE;\n+      else\n+        wait_timeout = timeout;\n+    }\n+\n+  for (;;)\n+    {\n+      ret = MsgWaitForMultipleObjects (nhandles, handle_array, FALSE,\n+                                       wait_timeout, QS_ALLINPUT);\n+\n+      if (ret == WAIT_OBJECT_0 + nhandles)\n+        {\n+          /* new input of some other kind */\n+          BOOL bRet;\n+          while ((bRet = PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) != 0)\n+            {\n+              TranslateMessage (&msg);\n+              DispatchMessage (&msg);\n+            }\n+        }\n+      else\n+        break;\n+    }\n+\n+  if (poll_again)\n+    select (0, &rfds, &wfds, &xfds, &tv0);\n+\n+  /* Place a sentinel at the end of the array.  */\n+  handle_array[nhandles] = NULL;\n+  nhandles = 1;\n+  for (i = 0; i < nfd; i++)\n+    {\n+      int happened;\n+\n+      if (pfd[i].fd < 0)\n+        continue;\n+      if (!(pfd[i].events & (POLLIN | POLLRDNORM |\n+                             POLLOUT | POLLWRNORM | POLLWRBAND)))\n+        continue;\n+\n+      h = (HANDLE) _get_osfhandle (pfd[i].fd);\n+      if (h != handle_array[nhandles])\n+        {\n+          /* It's a socket.  */\n+          WSAEnumNetworkEvents ((SOCKET) h, NULL, &ev);\n+          WSAEventSelect ((SOCKET) h, 0, 0);\n+\n+          /* If we're lucky, WSAEnumNetworkEvents already provided a way\n+             to distinguish FD_READ and FD_ACCEPT; this saves a recv later.  */\n+          if (FD_ISSET ((SOCKET) h, &rfds)\n+              && !(ev.lNetworkEvents & (FD_READ | FD_ACCEPT)))\n+            ev.lNetworkEvents |= FD_READ | FD_ACCEPT;\n+          if (FD_ISSET ((SOCKET) h, &wfds))\n+            ev.lNetworkEvents |= FD_WRITE | FD_CONNECT;\n+          if (FD_ISSET ((SOCKET) h, &xfds))\n+            ev.lNetworkEvents |= FD_OOB;\n+\n+          happened = win32_compute_revents_socket ((SOCKET) h, pfd[i].events,\n+                                                   ev.lNetworkEvents);\n+        }\n+      else\n+        {\n+          /* Not a socket.  */\n+          int sought = pfd[i].events;\n+          happened = win32_compute_revents (h, &sought);\n+          nhandles++;\n+        }\n+\n+       if ((pfd[i].revents |= happened) != 0)\n+        rc++;\n+    }\n+\n+  return rc;\n+#endif\n+}\ndiff --git a/compat/win32/sys/poll.h b/compat/win32/sys/poll.h\nnew file mode 100644\nindex 0000000..b7aa59d\n--- /dev/null\n+++ b/compat/win32/sys/poll.h\n@@ -0,0 +1,53 @@\n+/* Header for poll(2) emulation\n+   Contributed by Paolo Bonzini.\n+\n+   Copyright 2001, 2002, 2003, 2007, 2009, 2010 Free Software Foundation, Inc.\n+\n+   This file is part of gnulib.\n+\n+   This program is free software; you can redistribute it and/or modify\n+   it under the terms of the GNU General Public License as published by\n+   the Free Software Foundation; either version 2, or (at your option)\n+   any later version.\n+\n+   This program is distributed in the hope that it will be useful,\n+   but WITHOUT ANY WARRANTY; without even the implied warranty of\n+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+   GNU General Public License for more details.\n+\n+   You should have received a copy of the GNU General Public License along\n+   with this program; if not, write to the Free Software Foundation,\n+   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */\n+\n+#ifndef _GL_POLL_H\n+#define _GL_POLL_H\n+\n+/* fake a poll(2) environment */\n+#define POLLIN      0x0001      /* any readable data available   */\n+#define POLLPRI     0x0002      /* OOB/Urgent readable data      */\n+#define POLLOUT     0x0004      /* file descriptor is writeable  */\n+#define POLLERR     0x0008      /* some poll error occurred      */\n+#define POLLHUP     0x0010      /* file descriptor was \"hung up\" */\n+#define POLLNVAL    0x0020      /* requested events \"invalid\"    */\n+#define POLLRDNORM  0x0040\n+#define POLLRDBAND  0x0080\n+#define POLLWRNORM  0x0100\n+#define POLLWRBAND  0x0200\n+\n+struct pollfd\n+{\n+  int fd;                       /* which file descriptor to poll */\n+  short events;                 /* events we are interested in   */\n+  short revents;                /* events found on return        */\n+};\n+\n+typedef unsigned long nfds_t;\n+\n+extern int poll (struct pollfd *pfd, nfds_t nfd, int timeout);\n+\n+/* Define INFTIM only if doing so conforms to POSIX.  */\n+#if !defined (_POSIX_C_SOURCE) && !defined (_XOPEN_SOURCE)\n+#define INFTIM (-1)\n+#endif\n+\n+#endif /* _GL_POLL_H */\n-- \n1.7.3.2.161.gd6e00\n"},{"id":"155063","messageId":"1288801894-1168-14-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 13/16] mingw: use poll-emulation from gnulib","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:31Z","receivedAt":"2010-11-03T16:31:31Z","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 Makefile                |    6 +++-\n compat/mingw.c          |   65 -----------------------------------------------\n compat/mingw.h          |   11 --------\n compat/win32/sys/poll.c |    3 +-\n git-compat-util.h       |    2 +-\n 5 files changed, 6 insertions(+), 81 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 2aa067a..46034bf 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -497,6 +497,7 @@ LIB_H += compat/cygwin.h\n LIB_H += compat/mingw.h\n LIB_H += compat/win32/pthread.h\n LIB_H += compat/win32/syslog.h\n+LIB_H += compat/win32/sys/poll.h\n LIB_H += csum-file.h\n LIB_H += decorate.h\n LIB_H += delta.h\n@@ -1082,7 +1083,7 @@ ifeq ($(uname_S),Windows)\n \tAR = compat/vcbuild/scripts/lib.pl\n \tCFLAGS =\n \tBASIC_CFLAGS = -nologo -I. -I../zlib -Icompat/vcbuild -Icompat/vcbuild/include -DWIN32 -D_CONSOLE -DHAVE_STRING_H -D_CRT_SECURE_NO_WARNINGS -D_CRT_NONSTDC_NO_DEPRECATE\n-\tCOMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o compat/win32/syslog.o\n+\tCOMPAT_OBJS = compat/msvc.o compat/fnmatch/fnmatch.o compat/winansi.o compat/win32/pthread.o compat/win32/syslog.o compat/win32/sys/poll.o\n \tCOMPAT_CFLAGS = -D__USE_MINGW_ACCESS -DNOGDI -DHAVE_STRING_H -DHAVE_ALLOCA_H -Icompat -Icompat/fnmatch -Icompat/regex -Icompat/fnmatch -Icompat/win32 -DSTRIP_EXTENSION=\\\".exe\\\"\n \tBASIC_LDFLAGS = -IGNORE:4217 -IGNORE:4049 -NOLOGO -SUBSYSTEM:CONSOLE -NODEFAULTLIB:MSVCRT.lib\n \tEXTLIBS = advapi32.lib shell32.lib wininet.lib ws2_32.lib\n@@ -1132,7 +1133,8 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \\\n-\t\tcompat/win32/pthread.o compat/win32/syslog.o\n+\t\tcompat/win32/pthread.o compat/win32/syslog.o \\\n+\t\tcompat/win32/sys/poll.o\n \tEXTLIBS += -lws2_32\n \tPTHREAD_LIBS =\n \tX = .exe\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex d88c0d0..b780200 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -408,71 +408,6 @@ int pipe(int filedes[2])\n \treturn 0;\n }\n \n-int poll(struct pollfd *ufds, unsigned int nfds, int timeout)\n-{\n-\tint i, pending;\n-\n-\tif (timeout >= 0) {\n-\t\tif (nfds == 0) {\n-\t\t\tSleep(timeout);\n-\t\t\treturn 0;\n-\t\t}\n-\t\treturn errno = EINVAL, error(\"poll timeout not supported\");\n-\t}\n-\n-\t/* When there is only one fd to wait for, then we pretend that\n-\t * input is available and let the actual wait happen when the\n-\t * caller invokes read().\n-\t */\n-\tif (nfds == 1) {\n-\t\tif (!(ufds[0].events & POLLIN))\n-\t\t\treturn errno = EINVAL, error(\"POLLIN not set\");\n-\t\tufds[0].revents = POLLIN;\n-\t\treturn 0;\n-\t}\n-\n-repeat:\n-\tpending = 0;\n-\tfor (i = 0; i < nfds; i++) {\n-\t\tDWORD avail = 0;\n-\t\tHANDLE h = (HANDLE) _get_osfhandle(ufds[i].fd);\n-\t\tif (h == INVALID_HANDLE_VALUE)\n-\t\t\treturn -1;\t/* errno was set */\n-\n-\t\tif (!(ufds[i].events & POLLIN))\n-\t\t\treturn errno = EINVAL, error(\"POLLIN not set\");\n-\n-\t\t/* this emulation works only for pipes */\n-\t\tif (!PeekNamedPipe(h, NULL, 0, NULL, &avail, NULL)) {\n-\t\t\tint err = GetLastError();\n-\t\t\tif (err == ERROR_BROKEN_PIPE) {\n-\t\t\t\tufds[i].revents = POLLHUP;\n-\t\t\t\tpending++;\n-\t\t\t} else {\n-\t\t\t\terrno = EINVAL;\n-\t\t\t\treturn error(\"PeekNamedPipe failed,\"\n-\t\t\t\t\t\" GetLastError: %u\", err);\n-\t\t\t}\n-\t\t} else if (avail) {\n-\t\t\tufds[i].revents = POLLIN;\n-\t\t\tpending++;\n-\t\t} else\n-\t\t\tufds[i].revents = 0;\n-\t}\n-\tif (!pending) {\n-\t\t/* The only times that we spin here is when the process\n-\t\t * that is connected through the pipes is waiting for\n-\t\t * its own input data to become available. But since\n-\t\t * the process (pack-objects) is itself CPU intensive,\n-\t\t * it will happily pick up the time slice that we are\n-\t\t * relinquishing here.\n-\t\t */\n-\t\tSleep(0);\n-\t\tgoto repeat;\n-\t}\n-\treturn 0;\n-}\n-\n struct tm *gmtime_r(const time_t *timep, struct tm *result)\n {\n \t/* gmtime() in MSVCRT.DLL is thread-safe, but not reentrant */\ndiff --git a/compat/mingw.h b/compat/mingw.h\nindex 51fca2f..99a7467 100644\n--- a/compat/mingw.h\n+++ b/compat/mingw.h\n@@ -59,16 +59,6 @@ struct passwd {\n \n extern char *getpass(const char *prompt);\n \n-#ifndef POLLIN\n-struct pollfd {\n-\tint fd;           /* file descriptor */\n-\tshort events;     /* requested events */\n-\tshort revents;    /* returned events */\n-};\n-#define POLLIN 1\n-#define POLLHUP 2\n-#endif\n-\n typedef void (__cdecl *sig_handler_t)(int);\n struct sigaction {\n \tsig_handler_t sa_handler;\n@@ -175,7 +165,6 @@ int pipe(int filedes[2]);\n unsigned int sleep (unsigned int seconds);\n int mkstemp(char *template);\n int gettimeofday(struct timeval *tv, void *tz);\n-int poll(struct pollfd *ufds, unsigned int nfds, int timeout);\n struct tm *gmtime_r(const time_t *timep, struct tm *result);\n struct tm *localtime_r(const time_t *timep, struct tm *result);\n int getpagesize(void);\t/* defined in MinGW's libgcc.a */\ndiff --git a/compat/win32/sys/poll.c b/compat/win32/sys/poll.c\nindex 7c52cb6..c1ca0d2 100644\n--- a/compat/win32/sys/poll.c\n+++ b/compat/win32/sys/poll.c\n@@ -24,8 +24,7 @@\n # pragma GCC diagnostic ignored \"-Wtype-limits\"\n #endif\n \n-#include <config.h>\n-#include <alloca.h>\n+#include <malloc.h>\n \n #include <sys/types.h>\n #include \"poll.h\"\ndiff --git a/git-compat-util.h b/git-compat-util.h\nindex 56dce85..d0a1e48 100644\n--- a/git-compat-util.h\n+++ b/git-compat-util.h\n@@ -105,9 +105,9 @@\n #include <regex.h>\n #include <utime.h>\n #include <syslog.h>\n+#include <sys/poll.h>\n #ifndef __MINGW32__\n #include <sys/wait.h>\n-#include <sys/poll.h>\n #include <sys/socket.h>\n #include <sys/ioctl.h>\n #include <termios.h>\n-- \n1.7.3.2.161.gd6e00\n"},{"id":"155062","messageId":"1288801894-1168-15-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 14/16] daemon: use socklen_t","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:32Z","receivedAt":"2010-11-03T16:31:32Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Windows's accept()-function takes the last argument as an int, but glibc\ntakes an unsigned int. Use socklen_t to get rid of a warning. This is\nbasically a revert of 7fa0908, but we have already been depending on\nsocklen_t existing since June 2006 (commit 5b276ee4). I guess this means\nthat socklen_t IS defined on OSX after all - at least in recent headers.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n daemon.c |    6 +++---\n 1 files changed, 3 insertions(+), 3 deletions(-)\n\ndiff --git a/daemon.c b/daemon.c\nindex 3d8f6e6..5b30a2e 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -597,7 +597,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@@ -654,7 +654,7 @@ static void check_dead_children(void)\n }\n \n static 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 \tchar addrbuf[300] = \"REMOTE_ADDR=\", portbuf[300];\n@@ -904,7 +904,7 @@ static int service_loop(struct socketlist *socklist)\n \t\tfor (i = 0; i < socklist->nr; 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-- \n1.7.3.2.161.gd6e00\n"},{"id":"155071","messageId":"1288801894-1168-16-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 15/16] daemon: make --inetd and --detach incompatible","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:33Z","receivedAt":"2010-11-03T16:31:33Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Since --inetd makes main return with the result of execute() before\ndaemonize is gets called, these two options are already incompatible.\n\nDocument it, and add an error if attempted.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n Documentation/git-daemon.txt |    3 ++-\n daemon.c                     |    8 ++++----\n 2 files changed, 6 insertions(+), 5 deletions(-)\n\ndiff --git a/Documentation/git-daemon.txt b/Documentation/git-daemon.txt\nindex 5054f79..d15cb6a 100644\n--- a/Documentation/git-daemon.txt\n+++ b/Documentation/git-daemon.txt\n@@ -78,7 +78,8 @@ OPTIONS\n \n --inetd::\n \tHave the server run as an inetd service. Implies --syslog.\n-\tIncompatible with --port, --listen, --user and --group options.\n+\tIncompatible with --detach, --port, --listen, --user and --group\n+\toptions.\n \n --listen=<host_or_ipaddr>::\n \tListen on a specific IP address or hostname.  IP addresses can\ndiff --git a/daemon.c b/daemon.c\nindex 5b30a2e..485bec5 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -23,10 +23,10 @@ static const char daemon_usage[] =\n \"           [--strict-paths] [--base-path=<path>] [--base-path-relaxed]\\n\"\n \"           [--user-path | --user-path=<path>]\\n\"\n \"           [--interpolated-path=<path>]\\n\"\n-\"           [--reuseaddr] [--detach] [--pid-file=<file>]\\n\"\n+\"           [--reuseaddr] [--pid-file=<file>]\\n\"\n \"           [--(enable|disable|allow-override|forbid-override)=<service>]\\n\"\n \"           [--inetd | [--listen=<host_or_ipaddr>] [--port=<n>]\\n\"\n-\"                      [--user=<user> [--group=<group>]]\\n\"\n+\"                      [--detach] [--user=<user> [--group=<group>]]\\n\"\n \"           [<directory>...]\";\n \n /* List of acceptable pathname prefixes */\n@@ -1122,8 +1122,8 @@ int main(int argc, char **argv)\n \t\t/* avoid splitting a message in the middle */\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+\tif (inetd_mode && (detach || group_name || user_name))\n+\t\tdie(\"--detach, --user and --group are incompatible with --inetd\");\n \n \tif (inetd_mode && (listen_port || (listen_addr.nr > 0)))\n \t\tdie(\"--listen= and --port= are incompatible with --inetd\");\n-- \n1.7.3.2.161.gd6e00\n"},{"id":"155061","messageId":"1288801894-1168-17-git-send-email-kusmabite@gmail.com","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"[PATCH v6 16/16] daemon: opt-out on features that require posix","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T16:31:34Z","receivedAt":"2010-11-03T16:31:34Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"Windows does not supply the POSIX-functions fork(), setuuid(), setgid(),\nsetsid() and initgroups(). Error out if --user or --detach is specified\nwhen if so.\n\nMinGW doesn't have prototypes and headers for inet_ntop and inet_pton,\nso include our implementation instead. MSVC does, so avoid doing so\nthere.\n\nSigned-off-by: Erik Faye-Lund <kusmabite@gmail.com>\n---\n Makefile |   14 ++++++---\n daemon.c |   88 +++++++++++++++++++++++++++++++++++++++++++++-----------------\n 2 files changed, 73 insertions(+), 29 deletions(-)\n\ndiff --git a/Makefile b/Makefile\nindex 46034bf..53986b1 100644\n--- a/Makefile\n+++ b/Makefile\n@@ -401,6 +401,7 @@ EXTRA_PROGRAMS =\n # ... and all the rest that could be moved out of bindir to gitexecdir\n PROGRAMS += $(EXTRA_PROGRAMS)\n \n+PROGRAM_OBJS += daemon.o\n PROGRAM_OBJS += fast-import.o\n PROGRAM_OBJS += imap-send.o\n PROGRAM_OBJS += shell.o\n@@ -1066,7 +1067,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@@ -1077,6 +1077,7 @@ ifeq ($(uname_S),Windows)\n \tNO_CURL = YesPlease\n \tNO_PYTHON = YesPlease\n \tBLK_SHA1 = YesPlease\n+\tNO_POSIX_GOODIES = UnfortunatelyYes\n \tNATIVE_CRLF = YesPlease\n \n \tCC = compat/vcbuild/scripts/clink.pl\n@@ -1119,7 +1120,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@@ -1130,6 +1130,9 @@ ifneq (,$(findstring MINGW,$(uname_S)))\n \tNO_PYTHON = YesPlease\n \tBLK_SHA1 = YesPlease\n \tETAGS_TARGET = ETAGS\n+\tNO_INET_PTON = YesPlease\n+\tNO_INET_NTOP = YesPlease\n+\tNO_POSIX_GOODIES = UnfortunatelyYes\n \tCOMPAT_CFLAGS += -D__USE_MINGW_ACCESS -DNOGDI -Icompat -Icompat/fnmatch -Icompat/win32\n \tCOMPAT_CFLAGS += -DSTRIP_EXTENSION=\\\".exe\\\"\n \tCOMPAT_OBJS += compat/mingw.o compat/fnmatch/fnmatch.o compat/winansi.o \\\n@@ -1249,9 +1252,6 @@ ifdef ZLIB_PATH\n endif\n EXTLIBS += -lz\n \n-ifndef NO_POSIX_ONLY_PROGRAMS\n-\tPROGRAM_OBJS += daemon.o\n-endif\n ifndef NO_OPENSSL\n \tOPENSSL_LIBSSL = -lssl\n \tifdef OPENSSLDIR\n@@ -1419,6 +1419,10 @@ ifdef NO_DEFLATE_BOUND\n \tBASIC_CFLAGS += -DNO_DEFLATE_BOUND\n endif\n \n+ifdef NO_POSIX_GOODIES\n+\tBASIC_CFLAGS += -DNO_POSIX_GOODIES\n+endif\n+\n ifdef BLK_SHA1\n \tSHA1_HEADER = \"block-sha1/sha1.h\"\n \tLIB_OBJS += block-sha1/sha1.o\ndiff --git a/daemon.c b/daemon.c\nindex 485bec5..299201f 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -934,6 +934,62 @@ static void sanitize_stdfds(void)\n \t\tclose(fd);\n }\n \n+#ifdef NO_POSIX_GOODIES\n+\n+struct credentials;\n+\n+static void drop_privileges(struct credentials *cred)\n+{\n+\t/* nothing */\n+}\n+\n+static void daemonize(void)\n+{\n+\tdie(\"--detach not supported on this platform\");\n+}\n+\n+static struct credentials *prepare_credentials(const char *user_name,\n+    const char *group_name)\n+{\n+\tdie(\"--user not supported on this platform\");\n+}\n+\n+#else\n+\n+struct credentials {\n+\tstruct passwd *pass;\n+\tgid_t gid;\n+};\n+\n+static void drop_privileges(struct credentials *cred)\n+{\n+\tif (cred && (initgroups(cred->pass->pw_name, cred->gid) ||\n+\t    setgid (cred->gid) || setuid(cred->pass->pw_uid)))\n+\t\tdie(\"cannot drop privileges\");\n+}\n+\n+static struct credentials *prepare_credentials(const char *user_name,\n+    const char *group_name)\n+{\n+\tstatic struct credentials c;\n+\n+\tc.pass = getpwnam(user_name);\n+\tif (!c.pass)\n+\t\tdie(\"user not found - %s\", user_name);\n+\n+\tif (!group_name)\n+\t\tc.gid = c.pass->pw_gid;\n+\telse {\n+\t\tstruct group *group = getgrnam(group_name);\n+\t\tif (!group)\n+\t\t\tdie(\"group not found - %s\", group_name);\n+\n+\t\tc.gid = group->gr_gid;\n+\t}\n+\n+\treturn &c;\n+}\n+\n static void daemonize(void)\n {\n \tswitch (fork()) {\n@@ -951,6 +1007,7 @@ static void daemonize(void)\n \tclose(2);\n \tsanitize_stdfds();\n }\n+#endif\n \n static void store_pid(const char *path)\n {\n@@ -961,7 +1018,8 @@ static void store_pid(const char *path)\n \t\tdie_errno(\"failed to write pid file '%s'\", path);\n }\n \n-static int serve(struct string_list *listen_addr, int listen_port, struct passwd *pass, gid_t gid)\n+static int serve(struct string_list *listen_addr, int listen_port,\n+    struct credentials *cred)\n {\n \tstruct socketlist socklist = { NULL, 0, 0 };\n \n@@ -970,10 +1028,7 @@ static int serve(struct string_list *listen_addr, int listen_port, struct passwd\n \t\tdie(\"unable to allocate any listen sockets on port %u\",\n \t\t    listen_port);\n \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+\tdrop_privileges(cred);\n \n \treturn service_loop(&socklist);\n }\n@@ -985,9 +1040,7 @@ int main(int argc, char **argv)\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-\tstruct group *group;\n-\tgid_t gid = 0;\n+\tstruct credentials *cred = NULL;\n \tint i;\n \n \tgit_extract_argv0_path(argv[0]);\n@@ -1133,21 +1186,8 @@ int main(int argc, char **argv)\n \tif (group_name && !user_name)\n \t\tdie(\"--group supplied without --user\");\n \n-\tif (user_name) {\n-\t\tpass = getpwnam(user_name);\n-\t\tif (!pass)\n-\t\t\tdie(\"user not found - %s\", user_name);\n-\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\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-\t}\n+\tif (user_name)\n+\t\tcred = prepare_credentials(user_name, group_name);\n \n \tif (strict_paths && (!ok_paths || !*ok_paths))\n \t\tdie(\"option --strict-paths requires a whitelist\");\n@@ -1181,5 +1221,5 @@ int main(int argc, char **argv)\n \tcld_argv[argc] = \"--serve\";\n \tcld_argv[argc+1] = NULL;\n \n-\treturn serve(&listen_addr, listen_port, pass, gid);\n+\treturn serve(&listen_addr, listen_port, cred);\n }\n-- \n1.7.3.2.161.gd6e00\n"},{"id":"155087","messageId":"877hgunmdc.fsf@fox.patthoyts.tk","threadId":"25629","inReplyTo":"1288801894-1168-1-git-send-email-kusmabite@gmail.com","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Pat Thoyts","fromEmail":"patthoyts@users.sourceforge.net","sentAt":"2010-11-03T21:11:27Z","receivedAt":"2010-11-03T21:11:27Z","isPatch":true,"sender":{"key":"patthoyts@users.sourceforge.net","avatar":"https://avatars.githubusercontent.com/u/30739?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n>Here's hopefully the last iteration of this series. The previous version\n>only got a single complain about a typo in the subject of patch 14/15, so\n>it seems like most controversies have been settled.\n\nI pulled this win32-daemon branch into my msysgit build tree and built\nit. I get the following warnings:\n\n    CC daemon.o\ndaemon.c: In function 'service_loop':\ndaemon.c:674: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\ndaemon.c:676: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\ndaemon.c:681: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\ndaemon.c:919: note: initialized from here\ndaemon.c:679: warning: dereferencing pointer 'sin_addr' does break strict-aliasing rules\ndaemon.c:675: note: initialized from here\ndaemon.c:691: warning: dereferencing pointer 'sin6_addr' does break strict-aliasing rules\ndaemon.c:682: note: initialized from here\n\nOtherwise it builds clean. The daemon running on Windows7 seems to be\nworking fine for both ipv4 and ipv6 connections (I tried both).\n\nHowever, monitoring the resource usage in procexp it looks like there is\na handle leak. Each 'git ls-remote' over ipv6 is gaining 16 handles that\ndo not appear to be released. They're all process handles for dead\nprocesses it looks like, so possibly there is a missing waitpid() or\nsomething similar for the 'git daemon -serve' subprocess. Doing this\nover ipv4 leaks 2 handles per request.\n\n-- \nPat Thoyts                            http://www.patthoyts.tk/\nPGP fingerprint 2C 6E 98 07 2C 59 C8 97  10 CE 11 E6 04 E0 B9 DD\n"},{"id":"155090","messageId":"AANLkTin2BCxDoKhDCSgSRG1eVUGVeQh6Bq_=FfAe0M_M@mail.gmail.com","threadId":"25629","inReplyTo":"877hgunmdc.fsf@fox.patthoyts.tk","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T22:18:38Z","receivedAt":"2010-11-03T22:18:38Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Wed, Nov 3, 2010 at 10:11 PM, Pat Thoyts\n<patthoyts@users.sourceforge.net> wrote:\n> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>\n>>Here's hopefully the last iteration of this series. The previous version\n>>only got a single complain about a typo in the subject of patch 14/15, so\n>>it seems like most controversies have been settled.\n>\n> I pulled this win32-daemon branch into my msysgit build tree and built\n> it. I get the following warnings:\n>\n>    CC daemon.o\n> daemon.c: In function 'service_loop':\n> daemon.c:674: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n> daemon.c:676: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n> daemon.c:681: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n> daemon.c:919: note: initialized from here\n> daemon.c:679: warning: dereferencing pointer 'sin_addr' does break strict-aliasing rules\n> daemon.c:675: note: initialized from here\n> daemon.c:691: warning: dereferencing pointer 'sin6_addr' does break strict-aliasing rules\n> daemon.c:682: note: initialized from here\n>\n\nYeah, I'm aware of these. I thought those warnings were already\npresent in the Linux build, but checking again I see that that's not\nthe case. Need to investigate.\n\n> Otherwise it builds clean. The daemon running on Windows7 seems to be\n> working fine for both ipv4 and ipv6 connections (I tried both).\n>\n> However, monitoring the resource usage in procexp it looks like there is\n> a handle leak. Each 'git ls-remote' over ipv6 is gaining 16 handles that\n> do not appear to be released. They're all process handles for dead\n> processes it looks like, so possibly there is a missing waitpid() or\n> something similar for the 'git daemon -serve' subprocess. Doing this\n> over ipv4 leaks 2 handles per request.\n>\n\nAh, thanks. For me it's leaking a variable amount of handles per\nls-remote, but if I apply the following patch it's down to one. Need\nto find that one as well...\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex b780200..47e7d26 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -1519,8 +1519,10 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n \t}\n\n \tif (pid > 0 && options & WNOHANG) {\n-\t\tif (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n+\t\tif (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0)) {\n+\t\t\tCloseHandle(h);\n \t\t\treturn 0;\n+\t\t}\n \t\toptions &= ~WNOHANG;\n \t}\n"},{"id":"155093","messageId":"AANLkTin6120QbxyxHt=UM9Dpk_3C-vaD2z8RaRuut76r@mail.gmail.com","threadId":"25629","inReplyTo":"AANLkTin2BCxDoKhDCSgSRG1eVUGVeQh6Bq_=FfAe0M_M@mail.gmail.com","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T22:39:34Z","receivedAt":"2010-11-03T22:39:34Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Wed, Nov 3, 2010 at 11:18 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> Ah, thanks. For me it's leaking a variable amount of handles per\n> ls-remote, but if I apply the following patch it's down to one. Need\n> to find that one as well...\n>\n> diff --git a/compat/mingw.c b/compat/mingw.c\n> index b780200..47e7d26 100644\n> --- a/compat/mingw.c\n> +++ b/compat/mingw.c\n> @@ -1519,8 +1519,10 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n>        }\n>\n>        if (pid > 0 && options & WNOHANG) {\n> -               if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n> +               if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0)) {\n\nAAAND the last one is right here as well:\n-\t\tif (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n+\t\tif (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) {\n"},{"id":"155094","messageId":"AANLkTim4_5dgPGcw5B3U-3UH63REL4QWsWPV=mDSJJ6D@mail.gmail.com","threadId":"25629","inReplyTo":"AANLkTin2BCxDoKhDCSgSRG1eVUGVeQh6Bq_=FfAe0M_M@mail.gmail.com","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-03T22:58:42Z","receivedAt":"2010-11-03T22:58:42Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Wed, Nov 3, 2010 at 11:18 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> On Wed, Nov 3, 2010 at 10:11 PM, Pat Thoyts\n> <patthoyts@users.sourceforge.net> wrote:\n>> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>>\n>>>Here's hopefully the last iteration of this series. The previous version\n>>>only got a single complain about a typo in the subject of patch 14/15, so\n>>>it seems like most controversies have been settled.\n>>\n>> I pulled this win32-daemon branch into my msysgit build tree and built\n>> it. I get the following warnings:\n>>\n>>    CC daemon.o\n>> daemon.c: In function 'service_loop':\n>> daemon.c:674: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>> daemon.c:676: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>> daemon.c:681: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>> daemon.c:919: note: initialized from here\n>> daemon.c:679: warning: dereferencing pointer 'sin_addr' does break strict-aliasing rules\n>> daemon.c:675: note: initialized from here\n>> daemon.c:691: warning: dereferencing pointer 'sin6_addr' does break strict-aliasing rules\n>> daemon.c:682: note: initialized from here\n>>\n>\n> Yeah, I'm aware of these. I thought those warnings were already\n> present in the Linux build, but checking again I see that that's not\n> the case. Need to investigate.\n>\n\nOK, it's the patch \"daemon: use run-command api for async serving\"\nthat introduce the warning. But looking closer at the patch it doesn't\nseem the patch actually introduce the strict-aliasing violation, it's\nthere already. The patch only seems to change the code enough for GCC\nto start realize there's a problem. Unless I'm misunderstanding\nsomething vital, that is.\n\nAnyway, here's a patch that makes it go away, I guess I'll squash it\ninto the next round.\n\ndiff --git a/daemon.c b/daemon.c\nindex 6eee570..d636446 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -1159,14 +1159,13 @@ int main(int argc, char **argv)\n \t}\n\n \tif (inetd_mode || serve_mode) {\n-\t\tstruct sockaddr_storage ss;\n-\t\tstruct sockaddr *peer = (struct sockaddr *)&ss;\n-\t\tsocklen_t slen = sizeof(ss);\n+\t\tstruct sockaddr sa;\n+\t\tsocklen_t slen = sizeof(sa);\n\n-\t\tif (getpeername(0, peer, &slen))\n-\t\t\tpeer = NULL;\n-\n-\t\treturn execute(peer);\n+\t\tif (getpeername(0, &sa, &slen))\n+\t\t\treturn execute(NULL);\n+\t\telse\n+\t\t\treturn execute(&sa);\n \t}\n\n \tif (detach) {\n"},{"id":"155095","messageId":"AANLkTin6_RLBJZKDaDViZ2_v7_LKpyoyvofowArx9sas@mail.gmail.com","threadId":"25629","inReplyTo":"AANLkTim4_5dgPGcw5B3U-3UH63REL4QWsWPV=mDSJJ6D@mail.gmail.com","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-04T00:06:17Z","receivedAt":"2010-11-04T00:06:17Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Wed, Nov 3, 2010 at 11:58 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> On Wed, Nov 3, 2010 at 11:18 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>> On Wed, Nov 3, 2010 at 10:11 PM, Pat Thoyts\n>> <patthoyts@users.sourceforge.net> wrote:\n>>> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>>>\n>>>>Here's hopefully the last iteration of this series. The previous version\n>>>>only got a single complain about a typo in the subject of patch 14/15, so\n>>>>it seems like most controversies have been settled.\n>>>\n>>> I pulled this win32-daemon branch into my msysgit build tree and built\n>>> it. I get the following warnings:\n>>>\n>>>    CC daemon.o\n>>> daemon.c: In function 'service_loop':\n>>> daemon.c:674: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>>> daemon.c:676: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>>> daemon.c:681: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>>> daemon.c:919: note: initialized from here\n>>> daemon.c:679: warning: dereferencing pointer 'sin_addr' does break strict-aliasing rules\n>>> daemon.c:675: note: initialized from here\n>>> daemon.c:691: warning: dereferencing pointer 'sin6_addr' does break strict-aliasing rules\n>>> daemon.c:682: note: initialized from here\n>>>\n>>\n>> Yeah, I'm aware of these. I thought those warnings were already\n>> present in the Linux build, but checking again I see that that's not\n>> the case. Need to investigate.\n>>\n>\n> OK, it's the patch \"daemon: use run-command api for async serving\"\n> that introduce the warning. But looking closer at the patch it doesn't\n> seem the patch actually introduce the strict-aliasing violation, it's\n> there already. The patch only seems to change the code enough for GCC\n> to start realize there's a problem. Unless I'm misunderstanding\n> something vital, that is.\n>\n> Anyway, here's a patch that makes it go away, I guess I'll squash it\n> into the next round.\n>\n\nI also of course need to update \"daemon: get remote host address from\nroot-process\" as well, as it introduces a new such code-path (which is\nactually the one complained about here). And I guess I should use\nsockaddr_in instead of sockaddr.\n\nBut my luck stops there. The resulting git-daemon.exe leaves me with a\nvery bizarre error:\n\nerror: unable to make a socket file descriptor: Bad file descriptor\nfatal: accept returned: Bad file descriptor\n\nThis is triggered by the call to accept() in mingw_accept returning -1.\n\nWhat is even stranger is that if I change the code at the error-point like this\n-\t\t\t\tstruct sockaddr_in sa;\n+\t\t\t\tstruct sockaddr_in sa[2];\n \t\t\t\tsocklen_t salen = sizeof(sa);\n-\t\t\t\tint incoming = accept(pfd[i].fd, (struct sockaddr *)&sa, &salen);\n+\t\t\t\tint incoming = accept(pfd[i].fd, (struct sockaddr *)sa, &salen);\n\nthe error goes away. Similarly, if I change mingw_accept's call to\nWinsock's accept(), like this:\n-\tSOCKET s2 = accept(s1, sa, sz);\n+\tSOCKET s2 = accept(s1, sa, NULL);\n\nSo it seems accept() somehow reacts to the value of the variable\npointed at by sz, which is 16. Strange, huh?\n\nPerhaps it isn't -- the sockaddr_storage change seems to have been\nintroduced for IPv6 reasons. I'm trying to connect over IPv6, and IPv6\nhas a new sockaddr_in6 struct. So yeah.\n\nStuffing all of sockaddr, sockaddr_in and sockaddr_in6 (when built\nwith IPv6 support) in a union and passing that around instead does\nseem to fix the issue completely. I don't find it very elegant, but\nsome google-searches on the issue seems to reveal that this is the\nonly way of getting rid of this. Any other suggestions, people?\n"},{"id":"155098","messageId":"8739rind8u.fsf@fox.patthoyts.tk","threadId":"25629","inReplyTo":"AANLkTin6120QbxyxHt=UM9Dpk_3C-vaD2z8RaRuut76r@mail.gmail.com","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Pat Thoyts","fromEmail":"patthoyts@users.sourceforge.net","sentAt":"2010-11-04T00:28:33Z","receivedAt":"2010-11-04T00:28:33Z","isPatch":true,"sender":{"key":"patthoyts@users.sourceforge.net","avatar":"https://avatars.githubusercontent.com/u/30739?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n>On Wed, Nov 3, 2010 at 11:18 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>> Ah, thanks. For me it's leaking a variable amount of handles per\n>> ls-remote, but if I apply the following patch it's down to one. Need\n>> to find that one as well...\n>>\n>> diff --git a/compat/mingw.c b/compat/mingw.c\n>> index b780200..47e7d26 100644\n>> --- a/compat/mingw.c\n>> +++ b/compat/mingw.c\n>> @@ -1519,8 +1519,10 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n>>        }\n>>\n>>        if (pid > 0 && options & WNOHANG) {\n>> -               if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n>> +               if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0)) {\n>\n>AAAND the last one is right here as well:\n>-\t\tif (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n>+\t\tif (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) {\n>\n\nApplying both of these doesn't fix the handle leak when I test\nthis. Looking further I believe it is due to the use of a reallocated\narray. When you remove a pinfo structure you realloc to the one you\nfound, potentially freeing items you still require.\n\nAttached is a patch that switches to a linked list for this\ninstead. Using this I no longer accumulate leaked handles.\n\n----\nFrom e0c05f8f9ed8729648eea92cf654f357fa884e40 Mon Sep 17 00:00:00 2001\nFrom: Pat Thoyts <patthoyts@users.sourceforge.net>\nDate: Thu, 4 Nov 2010 00:23:08 +0000\nSubject: [PATCH] win32-daemon: fix handle leaks\n\nThe use of an array of pinfo structures and the realloc used when cleaning\nup a closed child can free structures that are still in use. Use a linked\nlist instead.\nThis stops the leaking of handles in the win32-daemon.\n\nSigned-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>\n---\n compat/mingw.c |   43 ++++++++++++++++++++++++-------------------\n 1 files changed, 24 insertions(+), 19 deletions(-)\n\ndiff --git a/compat/mingw.c b/compat/mingw.c\nindex b780200..29f4036 100644\n--- a/compat/mingw.c\n+++ b/compat/mingw.c\n@@ -637,11 +637,12 @@ static int env_compare(const void *a, const void *b)\n \treturn strcasecmp(*ea, *eb);\n }\n \n-struct {\n+struct pinfo_t {\n+\tstruct pinfo_t *next;\n \tpid_t pid;\n \tHANDLE proc;\n-} *pinfo;\n-static int num_pinfo;\n+} pinfo_t;\n+struct pinfo_t *pinfo = NULL;\n CRITICAL_SECTION pinfo_cs;\n \n static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,\n@@ -746,10 +747,13 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,\n \t * Keep the handle in a list for waitpid.\n \t */\n \tEnterCriticalSection(&pinfo_cs);\n-\tnum_pinfo++;\n-\tpinfo = xrealloc(pinfo, sizeof(*pinfo) * num_pinfo);\n-\tpinfo[num_pinfo - 1].pid = pi.dwProcessId;\n-\tpinfo[num_pinfo - 1].proc = pi.hProcess;\n+\t{\n+\t\tstruct pinfo_t *info = xmalloc(sizeof(struct pinfo_t));\n+\t\tinfo->pid = pi.dwProcessId;\n+\t\tinfo->proc = pi.hProcess;\n+\t\tinfo->next = pinfo;\n+\t\tpinfo = info;\n+\t}\n \tLeaveCriticalSection(&pinfo_cs);\n \n \treturn (pid_t)pi.dwProcessId;\n@@ -1519,13 +1523,15 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n \t}\n \n \tif (pid > 0 && options & WNOHANG) {\n-\t\tif (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n+\t\tif (WAIT_OBJECT_0 != WaitForSingleObject(h, 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\tint i;\n+\t\tstruct pinfo_t **ppinfo;\n \t\tif (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {\n \t\t\tCloseHandle(h);\n \t\t\treturn 0;\n@@ -1536,17 +1542,16 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n \n \t\tEnterCriticalSection(&pinfo_cs);\n \n-\t\tfor (i = 0; i < num_pinfo; ++i)\n-\t\t\tif (pinfo[i].pid == pid)\n+\t\tppinfo = &pinfo;\n+\t\twhile (*ppinfo) {\n+\t\t\tstruct pinfo_t *info = *ppinfo;\n+\t\t\tif (info->pid == pid) {\n+\t\t\t\tCloseHandle(info->proc);\n+\t\t\t\t*ppinfo = info->next;\n+\t\t\t\tfree(info);\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(*pinfo) * (num_pinfo - i - 1));\n-\t\t\tnum_pinfo--;\n-\t\t\tpinfo = xrealloc(pinfo,\n-\t\t\t    sizeof(*pinfo) * num_pinfo);\n+\t\t\t}\n+\t\t\tppinfo = &info->next;\n \t\t}\n \n \t\tLeaveCriticalSection(&pinfo_cs);\n-- \n1.7.3.1.210.g3526b.dirty\n"},{"id":"155099","messageId":"AANLkTinS2PLD3qwHpf491J3bDjXO8PxF96KdF=fz9a8o@mail.gmail.com","threadId":"25629","inReplyTo":"AANLkTin6_RLBJZKDaDViZ2_v7_LKpyoyvofowArx9sas@mail.gmail.com","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-04T00:28:48Z","receivedAt":"2010-11-04T00:28:48Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Thu, Nov 4, 2010 at 1:06 AM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> On Wed, Nov 3, 2010 at 11:58 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>> On Wed, Nov 3, 2010 at 11:18 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>>> On Wed, Nov 3, 2010 at 10:11 PM, Pat Thoyts\n>>> <patthoyts@users.sourceforge.net> wrote:\n>>>> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>>>>\n>>>>>Here's hopefully the last iteration of this series. The previous version\n>>>>>only got a single complain about a typo in the subject of patch 14/15, so\n>>>>>it seems like most controversies have been settled.\n>>>>\n>>>> I pulled this win32-daemon branch into my msysgit build tree and built\n>>>> it. I get the following warnings:\n>>>>\n>>>>    CC daemon.o\n>>>> daemon.c: In function 'service_loop':\n>>>> daemon.c:674: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>>>> daemon.c:676: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>>>> daemon.c:681: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>>>> daemon.c:919: note: initialized from here\n>>>> daemon.c:679: warning: dereferencing pointer 'sin_addr' does break strict-aliasing rules\n>>>> daemon.c:675: note: initialized from here\n>>>> daemon.c:691: warning: dereferencing pointer 'sin6_addr' does break strict-aliasing rules\n>>>> daemon.c:682: note: initialized from here\n>>>>\n>>>\n>>> Yeah, I'm aware of these. I thought those warnings were already\n>>> present in the Linux build, but checking again I see that that's not\n>>> the case. Need to investigate.\n>>>\n>>\n>> OK, it's the patch \"daemon: use run-command api for async serving\"\n>> that introduce the warning. But looking closer at the patch it doesn't\n>> seem the patch actually introduce the strict-aliasing violation, it's\n>> there already. The patch only seems to change the code enough for GCC\n>> to start realize there's a problem. Unless I'm misunderstanding\n>> something vital, that is.\n>>\n>> Anyway, here's a patch that makes it go away, I guess I'll squash it\n>> into the next round.\n>>\n>\n> Stuffing all of sockaddr, sockaddr_in and sockaddr_in6 (when built\n> with IPv6 support) in a union and passing that around instead does\n> seem to fix the issue completely. I don't find it very elegant, but\n> some google-searches on the issue seems to reveal that this is the\n> only way of getting rid of this. Any other suggestions, people?\n>\n\nJust for reference, this is the patch that fixes it. What do you think?\n\ndiff --git a/daemon.c b/daemon.c\nindex 941c095..8162f10 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -902,9 +903,15 @@ static int service_loop(struct socketlist *socklist)\n\n \t\tfor (i = 0; i < socklist->nr; i++) {\n \t\t\tif (pfd[i].revents & POLLIN) {\n-\t\t\t\tstruct sockaddr_storage ss;\n+\t\t\t\tunion {\n+\t\t\t\t\tstruct sockaddr sa;\n+\t\t\t\t\tstruct sockaddr_in sai;\n+#ifndef NO_IPV6\n+\t\t\t\t\tstruct sockaddr_in6 sai6;\n+#endif\n+\t\t\t\t} ss;\n \t\t\t\tunsigned int sslen = sizeof(ss);\n-\t\t\t\tint incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);\n+\t\t\t\tint incoming = accept(pfd[i].fd, &ss.sa, &sslen);\n \t\t\t\tif (incoming < 0) {\n \t\t\t\t\tswitch (errno) {\n \t\t\t\t\tcase EAGAIN:\n@@ -915,7 +922,7 @@ static int service_loop(struct socketlist *socklist)\n \t\t\t\t\t\tdie_errno(\"accept returned\");\n \t\t\t\t\t}\n \t\t\t\t}\n-\t\t\t\thandle(incoming, (struct sockaddr *)&ss, sslen);\n+\t\t\t\thandle(incoming, &ss.sa, sslen);\n \t\t\t}\n \t\t}\n \t}\n"},{"id":"155103","messageId":"AANLkTimcYdQD-En+SfkH5dkaxaWXveuA5Oz-Hn0Cf1v+@mail.gmail.com","threadId":"25629","inReplyTo":"8739rind8u.fsf@fox.patthoyts.tk","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-04T00:53:57Z","receivedAt":"2010-11-04T00:53:57Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Thu, Nov 4, 2010 at 1:28 AM, Pat Thoyts\n<patthoyts@users.sourceforge.net> wrote:\n> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>>On Wed, Nov 3, 2010 at 11:18 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>>> diff --git a/compat/mingw.c b/compat/mingw.c\n>>> index b780200..47e7d26 100644\n>>> --- a/compat/mingw.c\n>>> +++ b/compat/mingw.c\n>>> @@ -1519,8 +1519,10 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n>>>        }\n>>>\n>>>        if (pid > 0 && options & WNOHANG) {\n>>> -               if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n>>> +               if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0)) {\n>>\n>>AAAND the last one is right here as well:\n>>-              if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n>>+              if (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) {\n>>\n>\n> Applying both of these doesn't fix the handle leak when I test\n> this. Looking further I believe it is due to the use of a reallocated\n> array. When you remove a pinfo structure you realloc to the one you\n> found, potentially freeing items you still require.\n>\n\nIf this is the reason, then that's a bug. The code TRIES to do the\nright thing by memmove'ing the the entro to be deleted to the end.\nLooking over the code, I still don't see anyhing obviously wrong.\nBut...\n\n> Attached is a patch that switches to a linked list for this\n> instead. Using this I no longer accumulate leaked handles.\n>\n> ----\n> From e0c05f8f9ed8729648eea92cf654f357fa884e40 Mon Sep 17 00:00:00 2001\n> From: Pat Thoyts <patthoyts@users.sourceforge.net>\n> Date: Thu, 4 Nov 2010 00:23:08 +0000\n> Subject: [PATCH] win32-daemon: fix handle leaks\n>\n> The use of an array of pinfo structures and the realloc used when cleaning\n> up a closed child can free structures that are still in use. Use a linked\n> list instead.\n> This stops the leaking of handles in the win32-daemon.\n>\n> Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>\n> ---\n>  compat/mingw.c |   43 ++++++++++++++++++++++++-------------------\n>  1 files changed, 24 insertions(+), 19 deletions(-)\n>\n> diff --git a/compat/mingw.c b/compat/mingw.c\n> index b780200..29f4036 100644\n> --- a/compat/mingw.c\n> +++ b/compat/mingw.c\n> @@ -637,11 +637,12 @@ static int env_compare(const void *a, const void *b)\n>        return strcasecmp(*ea, *eb);\n>  }\n>\n> -struct {\n> +struct pinfo_t {\n> +       struct pinfo_t *next;\n>        pid_t pid;\n>        HANDLE proc;\n> -} *pinfo;\n> -static int num_pinfo;\n> +} pinfo_t;\n> +struct pinfo_t *pinfo = NULL;\n>  CRITICAL_SECTION pinfo_cs;\n>\n>  static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,\n> @@ -746,10 +747,13 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,\n>         * Keep the handle in a list for waitpid.\n>         */\n>        EnterCriticalSection(&pinfo_cs);\n> -       num_pinfo++;\n> -       pinfo = xrealloc(pinfo, sizeof(*pinfo) * num_pinfo);\n> -       pinfo[num_pinfo - 1].pid = pi.dwProcessId;\n> -       pinfo[num_pinfo - 1].proc = pi.hProcess;\n> +       {\n> +               struct pinfo_t *info = xmalloc(sizeof(struct pinfo_t));\n> +               info->pid = pi.dwProcessId;\n> +               info->proc = pi.hProcess;\n> +               info->next = pinfo;\n> +               pinfo = info;\n> +       }\n>        LeaveCriticalSection(&pinfo_cs);\n>\n>        return (pid_t)pi.dwProcessId;\n> @@ -1519,13 +1523,15 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n>        }\n>\n>        if (pid > 0 && options & WNOHANG) {\n> -               if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n> +               if (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) {\n> +                       CloseHandle(h);\n>                        return 0;\n> +               }\n>                options &= ~WNOHANG;\n>        }\n>\n>        if (options == 0) {\n> -               int i;\n> +               struct pinfo_t **ppinfo;\n>                if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {\n>                        CloseHandle(h);\n>                        return 0;\n> @@ -1536,17 +1542,16 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n>\n>                EnterCriticalSection(&pinfo_cs);\n>\n> -               for (i = 0; i < num_pinfo; ++i)\n> -                       if (pinfo[i].pid == pid)\n> +               ppinfo = &pinfo;\n> +               while (*ppinfo) {\n> +                       struct pinfo_t *info = *ppinfo;\n> +                       if (info->pid == pid) {\n> +                               CloseHandle(info->proc);\n> +                               *ppinfo = info->next;\n> +                               free(info);\n>                                break;\n> -\n> -               if (i < num_pinfo) {\n> -                       CloseHandle(pinfo[i].proc);\n> -                       memmove(pinfo + i, pinfo + i + 1,\n> -                           sizeof(*pinfo) * (num_pinfo - i - 1));\n> -                       num_pinfo--;\n> -                       pinfo = xrealloc(pinfo,\n> -                           sizeof(*pinfo) * num_pinfo);\n> +                       }\n> +                       ppinfo = &info->next;\n>                }\n>\n>                LeaveCriticalSection(&pinfo_cs);\n\n...yeah, using a linked list is more elegant. Do you mind if I snatch\nyour code and leave a comment in the commit message?\n"},{"id":"155106","messageId":"87r5f1x5jf.fsf@fox.patthoyts.tk","threadId":"25629","inReplyTo":"AANLkTimcYdQD-En+SfkH5dkaxaWXveuA5Oz-Hn0Cf1v+@mail.gmail.com","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Pat Thoyts","fromEmail":"patthoyts@users.sourceforge.net","sentAt":"2010-11-04T01:04:52Z","receivedAt":"2010-11-04T01:04:52Z","isPatch":true,"sender":{"key":"patthoyts@users.sourceforge.net","avatar":"https://avatars.githubusercontent.com/u/30739?v=4"},"body":"Erik Faye-Lund <kusmabite@gmail.com> writes:\n\n>On Thu, Nov 4, 2010 at 1:28 AM, Pat Thoyts\n><patthoyts@users.sourceforge.net> wrote:\n>> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>>>On Wed, Nov 3, 2010 at 11:18 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>>>> diff --git a/compat/mingw.c b/compat/mingw.c\n>>>> index b780200..47e7d26 100644\n>>>> --- a/compat/mingw.c\n>>>> +++ b/compat/mingw.c\n>>>> @@ -1519,8 +1519,10 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n>>>>        }\n>>>>\n>>>>        if (pid > 0 && options & WNOHANG) {\n>>>> -               if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n>>>> +               if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0)) {\n>>>\n>>>AAAND the last one is right here as well:\n>>>-              if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n>>>+              if (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) {\n>>>\n>>\n>> Applying both of these doesn't fix the handle leak when I test\n>> this. Looking further I believe it is due to the use of a reallocated\n>> array. When you remove a pinfo structure you realloc to the one you\n>> found, potentially freeing items you still require.\n>>\n>\n>If this is the reason, then that's a bug. The code TRIES to do the\n>right thing by memmove'ing the the entro to be deleted to the end.\n>Looking over the code, I still don't see anyhing obviously wrong.\n>But...\n>\n>> Attached is a patch that switches to a linked list for this\n>> instead. Using this I no longer accumulate leaked handles.\n>>\n>> ----\n>> From e0c05f8f9ed8729648eea92cf654f357fa884e40 Mon Sep 17 00:00:00 2001\n>> From: Pat Thoyts <patthoyts@users.sourceforge.net>\n>> Date: Thu, 4 Nov 2010 00:23:08 +0000\n>> Subject: [PATCH] win32-daemon: fix handle leaks\n>>\n>> The use of an array of pinfo structures and the realloc used when cleaning\n>> up a closed child can free structures that are still in use. Use a linked\n>> list instead.\n>> This stops the leaking of handles in the win32-daemon.\n>>\n>> Signed-off-by: Pat Thoyts <patthoyts@users.sourceforge.net>\n>> ---\n>>  compat/mingw.c |   43 ++++++++++++++++++++++++-------------------\n>>  1 files changed, 24 insertions(+), 19 deletions(-)\n>>\n>> diff --git a/compat/mingw.c b/compat/mingw.c\n>> index b780200..29f4036 100644\n>> --- a/compat/mingw.c\n>> +++ b/compat/mingw.c\n>> @@ -637,11 +637,12 @@ static int env_compare(const void *a, const void *b)\n>>        return strcasecmp(*ea, *eb);\n>>  }\n>>\n>> -struct {\n>> +struct pinfo_t {\n>> +       struct pinfo_t *next;\n>>        pid_t pid;\n>>        HANDLE proc;\n>> -} *pinfo;\n>> -static int num_pinfo;\n>> +} pinfo_t;\n>> +struct pinfo_t *pinfo = NULL;\n>>  CRITICAL_SECTION pinfo_cs;\n>>\n>>  static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,\n>> @@ -746,10 +747,13 @@ static pid_t mingw_spawnve_fd(const char *cmd, const char **argv, char **env,\n>>         * Keep the handle in a list for waitpid.\n>>         */\n>>        EnterCriticalSection(&pinfo_cs);\n>> -       num_pinfo++;\n>> -       pinfo = xrealloc(pinfo, sizeof(*pinfo) * num_pinfo);\n>> -       pinfo[num_pinfo - 1].pid = pi.dwProcessId;\n>> -       pinfo[num_pinfo - 1].proc = pi.hProcess;\n>> +       {\n>> +               struct pinfo_t *info = xmalloc(sizeof(struct pinfo_t));\n>> +               info->pid = pi.dwProcessId;\n>> +               info->proc = pi.hProcess;\n>> +               info->next = pinfo;\n>> +               pinfo = info;\n>> +       }\n>>        LeaveCriticalSection(&pinfo_cs);\n>>\n>>        return (pid_t)pi.dwProcessId;\n>> @@ -1519,13 +1523,15 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n>>        }\n>>\n>>        if (pid > 0 && options & WNOHANG) {\n>> -               if (WAIT_OBJECT_0 != WaitForSingleObject((HANDLE)pid, 0))\n>> +               if (WAIT_OBJECT_0 != WaitForSingleObject(h, 0)) {\n>> +                       CloseHandle(h);\n>>                        return 0;\n>> +               }\n>>                options &= ~WNOHANG;\n>>        }\n>>\n>>        if (options == 0) {\n>> -               int i;\n>> +               struct pinfo_t **ppinfo;\n>>                if (WaitForSingleObject(h, INFINITE) != WAIT_OBJECT_0) {\n>>                        CloseHandle(h);\n>>                        return 0;\n>> @@ -1536,17 +1542,16 @@ pid_t waitpid(pid_t pid, int *status, unsigned options)\n>>\n>>                EnterCriticalSection(&pinfo_cs);\n>>\n>> -               for (i = 0; i < num_pinfo; ++i)\n>> -                       if (pinfo[i].pid == pid)\n>> +               ppinfo = &pinfo;\n>> +               while (*ppinfo) {\n>> +                       struct pinfo_t *info = *ppinfo;\n>> +                       if (info->pid == pid) {\n>> +                               CloseHandle(info->proc);\n>> +                               *ppinfo = info->next;\n>> +                               free(info);\n>>                                break;\n>> -\n>> -               if (i < num_pinfo) {\n>> -                       CloseHandle(pinfo[i].proc);\n>> -                       memmove(pinfo + i, pinfo + i + 1,\n>> -                           sizeof(*pinfo) * (num_pinfo - i - 1));\n>> -                       num_pinfo--;\n>> -                       pinfo = xrealloc(pinfo,\n>> -                           sizeof(*pinfo) * num_pinfo);\n>> +                       }\n>> +                       ppinfo = &info->next;\n>>                }\n>>\n>>                LeaveCriticalSection(&pinfo_cs);\n>\n>...yeah, using a linked list is more elegant. Do you mind if I snatch\n>your code and leave a comment in the commit message?\n>\n\nSure. When I wrote the comment I'd forgotten about the memmove. So\nhmmm. However, I just pulled you win32-daemon branch and applied this\npatch on top. Now there are no more warnings so your union fix is\ngood. As I understand it thats the way to handle this particular\nwarning. ipv6 and ipv4 both still work fine as well.\n\nWith my patch a while true; do git ls-remote; done shows no more leaking\nhandles or memory. So the use of a list is fixing something. Looking\ngreat now.\n\n-- \nPat Thoyts                            http://www.patthoyts.tk/\nPGP fingerprint 2C 6E 98 07 2C 59 C8 97  10 CE 11 E6 04 E0 B9 DD\n"},{"id":"155143","messageId":"alpine.DEB.2.00.1011041026160.31519@cone.home.martin.st","threadId":"25629","inReplyTo":"AANLkTim4_5dgPGcw5B3U-3UH63REL4QWsWPV=mDSJJ6D@mail.gmail.com","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Martin Storsjö","fromEmail":"martin@martin.st","sentAt":"2010-11-04T08:52:37Z","receivedAt":"2010-11-04T08:52:37Z","isPatch":true,"sender":{"key":"martin@martin.st","avatar":"https://avatars.githubusercontent.com/u/69727?v=4"},"body":"On Wed, 3 Nov 2010, Erik Faye-Lund wrote:\n\n> On Wed, Nov 3, 2010 at 11:18 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> > On Wed, Nov 3, 2010 at 10:11 PM, Pat Thoyts\n> > <patthoyts@users.sourceforge.net> wrote:\n> >> Erik Faye-Lund <kusmabite@gmail.com> writes:\n> >>\n> >>>Here's hopefully the last iteration of this series. The previous version\n> >>>only got a single complain about a typo in the subject of patch 14/15, so\n> >>>it seems like most controversies have been settled.\n> >>\n> >> I pulled this win32-daemon branch into my msysgit build tree and built\n> >> it. I get the following warnings:\n> >>\n> >>    CC daemon.o\n> >> daemon.c: In function 'service_loop':\n> >> daemon.c:674: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n> >> daemon.c:676: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n> >> daemon.c:681: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n> >> daemon.c:919: note: initialized from here\n> >> daemon.c:679: warning: dereferencing pointer 'sin_addr' does break strict-aliasing rules\n> >> daemon.c:675: note: initialized from here\n> >> daemon.c:691: warning: dereferencing pointer 'sin6_addr' does break strict-aliasing rules\n> >> daemon.c:682: note: initialized from here\n> >>\n> >\n> > Yeah, I'm aware of these. I thought those warnings were already\n> > present in the Linux build, but checking again I see that that's not\n> > the case. Need to investigate.\n> >\n> \n> OK, it's the patch \"daemon: use run-command api for async serving\"\n> that introduce the warning. But looking closer at the patch it doesn't\n> seem the patch actually introduce the strict-aliasing violation, it's\n> there already. The patch only seems to change the code enough for GCC\n> to start realize there's a problem. Unless I'm misunderstanding\n> something vital, that is.\n> \n> Anyway, here's a patch that makes it go away, I guess I'll squash it\n> into the next round.\n> \n> diff --git a/daemon.c b/daemon.c\n> index 6eee570..d636446 100644\n> --- a/daemon.c\n> +++ b/daemon.c\n> @@ -1159,14 +1159,13 @@ int main(int argc, char **argv)\n>  \t}\n> \n>  \tif (inetd_mode || serve_mode) {\n> -\t\tstruct sockaddr_storage ss;\n> -\t\tstruct sockaddr *peer = (struct sockaddr *)&ss;\n> -\t\tsocklen_t slen = sizeof(ss);\n> +\t\tstruct sockaddr sa;\n> +\t\tsocklen_t slen = sizeof(sa);\n> \n> -\t\tif (getpeername(0, peer, &slen))\n> -\t\t\tpeer = NULL;\n> -\n> -\t\treturn execute(peer);\n> +\t\tif (getpeername(0, &sa, &slen))\n> +\t\t\treturn execute(NULL);\n> +\t\telse\n> +\t\t\treturn execute(&sa);\n>  \t}\n> \n>  \tif (detach) {\n\nAs you noticed later yourself, this is not right. You can get any kind of \nsockaddr back from getpeername. I'm not sure if any spec mandates that a \n\"normal\" sockaddr_in should fit into the base sockaddr, or if that just \nhappens by coincidence or sheer luck.\n\n// Martin"},{"id":"155142","messageId":"alpine.DEB.2.00.1011041053120.31519@cone.home.martin.st","threadId":"25629","inReplyTo":"AANLkTinS2PLD3qwHpf491J3bDjXO8PxF96KdF=fz9a8o@mail.gmail.com","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Martin Storsjö","fromEmail":"martin@martin.st","sentAt":"2010-11-04T08:58:47Z","receivedAt":"2010-11-04T08:58:47Z","isPatch":true,"sender":{"key":"martin@martin.st","avatar":"https://avatars.githubusercontent.com/u/69727?v=4"},"body":"On Thu, 4 Nov 2010, Erik Faye-Lund wrote:\n\n> On Thu, Nov 4, 2010 at 1:06 AM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> > On Wed, Nov 3, 2010 at 11:58 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> >> On Wed, Nov 3, 2010 at 11:18 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> >>> On Wed, Nov 3, 2010 at 10:11 PM, Pat Thoyts\n> >>> <patthoyts@users.sourceforge.net> wrote:\n> >>>> Erik Faye-Lund <kusmabite@gmail.com> writes:\n> >>>>\n> >>>>>Here's hopefully the last iteration of this series. The previous version\n> >>>>>only got a single complain about a typo in the subject of patch 14/15, so\n> >>>>>it seems like most controversies have been settled.\n> >>>>\n> >>>> I pulled this win32-daemon branch into my msysgit build tree and built\n> >>>> it. I get the following warnings:\n> >>>>\n> >>>>    CC daemon.o\n> >>>> daemon.c: In function 'service_loop':\n> >>>> daemon.c:674: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n> >>>> daemon.c:676: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n> >>>> daemon.c:681: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n> >>>> daemon.c:919: note: initialized from here\n> >>>> daemon.c:679: warning: dereferencing pointer 'sin_addr' does break strict-aliasing rules\n> >>>> daemon.c:675: note: initialized from here\n> >>>> daemon.c:691: warning: dereferencing pointer 'sin6_addr' does break strict-aliasing rules\n> >>>> daemon.c:682: note: initialized from here\n> >>>>\n> >>>\n> >>> Yeah, I'm aware of these. I thought those warnings were already\n> >>> present in the Linux build, but checking again I see that that's not\n> >>> the case. Need to investigate.\n> >>>\n> >>\n> >> OK, it's the patch \"daemon: use run-command api for async serving\"\n> >> that introduce the warning. But looking closer at the patch it doesn't\n> >> seem the patch actually introduce the strict-aliasing violation, it's\n> >> there already. The patch only seems to change the code enough for GCC\n> >> to start realize there's a problem. Unless I'm misunderstanding\n> >> something vital, that is.\n> >>\n> >> Anyway, here's a patch that makes it go away, I guess I'll squash it\n> >> into the next round.\n> >>\n> >\n> > Stuffing all of sockaddr, sockaddr_in and sockaddr_in6 (when built\n> > with IPv6 support) in a union and passing that around instead does\n> > seem to fix the issue completely. I don't find it very elegant, but\n> > some google-searches on the issue seems to reveal that this is the\n> > only way of getting rid of this. Any other suggestions, people?\n> >\n> \n> Just for reference, this is the patch that fixes it. What do you think?\n> \n> diff --git a/daemon.c b/daemon.c\n> index 941c095..8162f10 100644\n> --- a/daemon.c\n> +++ b/daemon.c\n> @@ -902,9 +903,15 @@ static int service_loop(struct socketlist *socklist)\n> \n>  \t\tfor (i = 0; i < socklist->nr; i++) {\n>  \t\t\tif (pfd[i].revents & POLLIN) {\n> -\t\t\t\tstruct sockaddr_storage ss;\n> +\t\t\t\tunion {\n> +\t\t\t\t\tstruct sockaddr sa;\n> +\t\t\t\t\tstruct sockaddr_in sai;\n> +#ifndef NO_IPV6\n> +\t\t\t\t\tstruct sockaddr_in6 sai6;\n> +#endif\n> +\t\t\t\t} ss;\n>  \t\t\t\tunsigned int sslen = sizeof(ss);\n> -\t\t\t\tint incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);\n> +\t\t\t\tint incoming = accept(pfd[i].fd, &ss.sa, &sslen);\n>  \t\t\t\tif (incoming < 0) {\n>  \t\t\t\t\tswitch (errno) {\n>  \t\t\t\t\tcase EAGAIN:\n> @@ -915,7 +922,7 @@ static int service_loop(struct socketlist *socklist)\n>  \t\t\t\t\t\tdie_errno(\"accept returned\");\n>  \t\t\t\t\t}\n>  \t\t\t\t}\n> -\t\t\t\thandle(incoming, (struct sockaddr *)&ss, sslen);\n> +\t\t\t\thandle(incoming, &ss.sa, sslen);\n>  \t\t\t}\n>  \t\t}\n>  \t}\n\nAs you say yourself, it's not elegant at all - sockaddr_storage is \nintended to be just that, an struct large enough to fit all the sockaddrs \nyou'll encounter on this platform, with all fields aligned in the same way \nas all the other sockaddr structs. You're supposed to be able to cast the \nsockaddr struct pointers like currently is done, although I'm not familiar \nwith the strict aliasing stuff well enough to know if anything else would \nbe required somewhere.\n\nI didn't see any of these hacks in the v7 patchset - did the warning go \naway by itself there?\n\nFWIW, the actual warning itself isn't directly related to any of the code \nworked on here, gcc just happens to realize it after some of these \nchanges. I'm able to trigger the same warnings on the current master, by \nsimply doing this change:\n\ndiff --git a/daemon.c b/daemon.c\nindex 5783e24..467cea2 100644\n--- a/daemon.c\n+++ b/daemon.c\n@@ -670,7 +670,6 @@ static void handle(int incoming, struct sockaddr \n*addr, int \n        dup2(incoming, 1);\n        close(incoming);\n \n-       exit(execute(addr));\n }\n \n static void child_handler(int signo)\n\n\n// Martin"},{"id":"155144","messageId":"AANLkTimzS1tnykzjoywaLdBUi4zhwzUC6bght0-vnaGO@mail.gmail.com","threadId":"25629","inReplyTo":"alpine.DEB.2.00.1011041053120.31519@cone.home.martin.st","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-04T09:15:20Z","receivedAt":"2010-11-04T09:15:20Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Thu, Nov 4, 2010 at 9:58 AM, Martin Storsjö <martin@martin.st> wrote:\n> On Thu, 4 Nov 2010, Erik Faye-Lund wrote:\n>\n>> On Thu, Nov 4, 2010 at 1:06 AM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>> > On Wed, Nov 3, 2010 at 11:58 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>> >> On Wed, Nov 3, 2010 at 11:18 PM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>> >>> On Wed, Nov 3, 2010 at 10:11 PM, Pat Thoyts\n>> >>> <patthoyts@users.sourceforge.net> wrote:\n>> >>>> Erik Faye-Lund <kusmabite@gmail.com> writes:\n>> >>>>\n>> >>>>>Here's hopefully the last iteration of this series. The previous version\n>> >>>>>only got a single complain about a typo in the subject of patch 14/15, so\n>> >>>>>it seems like most controversies have been settled.\n>> >>>>\n>> >>>> I pulled this win32-daemon branch into my msysgit build tree and built\n>> >>>> it. I get the following warnings:\n>> >>>>\n>> >>>>    CC daemon.o\n>> >>>> daemon.c: In function 'service_loop':\n>> >>>> daemon.c:674: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>> >>>> daemon.c:676: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>> >>>> daemon.c:681: warning: dereferencing pointer 'ss.124' does break strict-aliasing rules\n>> >>>> daemon.c:919: note: initialized from here\n>> >>>> daemon.c:679: warning: dereferencing pointer 'sin_addr' does break strict-aliasing rules\n>> >>>> daemon.c:675: note: initialized from here\n>> >>>> daemon.c:691: warning: dereferencing pointer 'sin6_addr' does break strict-aliasing rules\n>> >>>> daemon.c:682: note: initialized from here\n>> >>>>\n>> >>>\n>> >>> Yeah, I'm aware of these. I thought those warnings were already\n>> >>> present in the Linux build, but checking again I see that that's not\n>> >>> the case. Need to investigate.\n>> >>>\n>> >>\n>> >> OK, it's the patch \"daemon: use run-command api for async serving\"\n>> >> that introduce the warning. But looking closer at the patch it doesn't\n>> >> seem the patch actually introduce the strict-aliasing violation, it's\n>> >> there already. The patch only seems to change the code enough for GCC\n>> >> to start realize there's a problem. Unless I'm misunderstanding\n>> >> something vital, that is.\n>> >>\n>> >> Anyway, here's a patch that makes it go away, I guess I'll squash it\n>> >> into the next round.\n>> >>\n>> >\n>> > Stuffing all of sockaddr, sockaddr_in and sockaddr_in6 (when built\n>> > with IPv6 support) in a union and passing that around instead does\n>> > seem to fix the issue completely. I don't find it very elegant, but\n>> > some google-searches on the issue seems to reveal that this is the\n>> > only way of getting rid of this. Any other suggestions, people?\n>> >\n>>\n>> Just for reference, this is the patch that fixes it. What do you think?\n>>\n>> diff --git a/daemon.c b/daemon.c\n>> index 941c095..8162f10 100644\n>> --- a/daemon.c\n>> +++ b/daemon.c\n>> @@ -902,9 +903,15 @@ static int service_loop(struct socketlist *socklist)\n>>\n>>               for (i = 0; i < socklist->nr; i++) {\n>>                       if (pfd[i].revents & POLLIN) {\n>> -                             struct sockaddr_storage ss;\n>> +                             union {\n>> +                                     struct sockaddr sa;\n>> +                                     struct sockaddr_in sai;\n>> +#ifndef NO_IPV6\n>> +                                     struct sockaddr_in6 sai6;\n>> +#endif\n>> +                             } ss;\n>>                               unsigned int sslen = sizeof(ss);\n>> -                             int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);\n>> +                             int incoming = accept(pfd[i].fd, &ss.sa, &sslen);\n>>                               if (incoming < 0) {\n>>                                       switch (errno) {\n>>                                       case EAGAIN:\n>> @@ -915,7 +922,7 @@ static int service_loop(struct socketlist *socklist)\n>>                                               die_errno(\"accept returned\");\n>>                                       }\n>>                               }\n>> -                             handle(incoming, (struct sockaddr *)&ss, sslen);\n>> +                             handle(incoming, &ss.sa, sslen);\n>>                       }\n>>               }\n>>       }\n>\n> As you say yourself, it's not elegant at all - sockaddr_storage is\n> intended to be just that, an struct large enough to fit all the sockaddrs\n> you'll encounter on this platform, with all fields aligned in the same way\n> as all the other sockaddr structs. You're supposed to be able to cast the\n> sockaddr struct pointers like currently is done, although I'm not familiar\n> with the strict aliasing stuff well enough to know if anything else would\n> be required somewhere.\n>\n\nStrict aliasing isn't exactly about the structure being large enough\nor not, it's only being able to access a particular piece of memory\nthrough one type only (unless specificly marked with \"union\").\nsockaddr_storage is an attempt at fixing the storage-problem without\naddressing the type punning problem, which doesn't help us much.\n\n> I didn't see any of these hacks in the v7 patchset - did the warning go\n> away by itself there?\n>\n\nThe strict aliasing problem was (as I described earlier, and you\npointed out later in your email) already present in the code. All the\npatch did, was modify the code enough to make GCC realize it.\n\nSince the code is removed by a later patch (\"daemon: get remote host\naddress from root-process\"), I figured adding a union just to remove\nit was just noisy. So instead I changed the code enough for the\nwarning to go away again. It turned out that it was the assignment of\nNULL to \"peer\" that triggered the warning, so I made two calls to\nexecute() instead, one that pass NULL and one that pass \"peer\".\n\nThen in \"daemon: get remote host address from root-process\" which\ncauses a similar strict-aliasing issue (this time I'm the one who\nintroduced it, since the handle() code-path doesn't derefence \"addr\"),\nI fixed it with a union.\n\n> FWIW, the actual warning itself isn't directly related to any of the code\n> worked on here, gcc just happens to realize it after some of these\n> changes. I'm able to trigger the same warnings on the current master, by\n> simply doing this change:\n>\n> diff --git a/daemon.c b/daemon.c\n> index 5783e24..467cea2 100644\n> --- a/daemon.c\n> +++ b/daemon.c\n> @@ -670,7 +670,6 @@ static void handle(int incoming, struct sockaddr\n> *addr, int\n>        dup2(incoming, 1);\n>        close(incoming);\n>\n> -       exit(execute(addr));\n>  }\n>\n>  static void child_handler(int signo)\n>\n>\n> // Martin\n\nYeah, I already figured that one out, but thanks for making it clearer. :)\n\nSo a nice end-result of v7 is that we're good with strict aliasing,\nwhich means that it's not safe(er) to compile git-daemon on GCC with\n-O3.\n"},{"id":"155151","messageId":"alpine.DEB.2.00.1011041118200.31519@cone.home.martin.st","threadId":"25629","inReplyTo":"AANLkTimzS1tnykzjoywaLdBUi4zhwzUC6bght0-vnaGO@mail.gmail.com","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Martin Storsjö","fromEmail":"martin@martin.st","sentAt":"2010-11-04T09:35:15Z","receivedAt":"2010-11-04T09:35:15Z","isPatch":true,"sender":{"key":"martin@martin.st","avatar":"https://avatars.githubusercontent.com/u/69727?v=4"},"body":"On Thu, 4 Nov 2010, Erik Faye-Lund wrote:\n\n> On Thu, Nov 4, 2010 at 9:58 AM, Martin Storsjö <martin@martin.st> wrote:\n> > On Thu, 4 Nov 2010, Erik Faye-Lund wrote:\n> >\n> >> On Thu, Nov 4, 2010 at 1:06 AM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n> >> >\n> >> > Stuffing all of sockaddr, sockaddr_in and sockaddr_in6 (when built\n> >> > with IPv6 support) in a union and passing that around instead does\n> >> > seem to fix the issue completely. I don't find it very elegant, but\n> >> > some google-searches on the issue seems to reveal that this is the\n> >> > only way of getting rid of this. Any other suggestions, people?\n> >> >\n> >>\n> >> Just for reference, this is the patch that fixes it. What do you think?\n> >>\n> >> diff --git a/daemon.c b/daemon.c\n> >> index 941c095..8162f10 100644\n> >> --- a/daemon.c\n> >> +++ b/daemon.c\n> >> @@ -902,9 +903,15 @@ static int service_loop(struct socketlist *socklist)\n> >>\n> >>               for (i = 0; i < socklist->nr; i++) {\n> >>                       if (pfd[i].revents & POLLIN) {\n> >> -                             struct sockaddr_storage ss;\n> >> +                             union {\n> >> +                                     struct sockaddr sa;\n> >> +                                     struct sockaddr_in sai;\n> >> +#ifndef NO_IPV6\n> >> +                                     struct sockaddr_in6 sai6;\n> >> +#endif\n> >> +                             } ss;\n> >>                               unsigned int sslen = sizeof(ss);\n> >> -                             int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);\n> >> +                             int incoming = accept(pfd[i].fd, &ss.sa, &sslen);\n> >>                               if (incoming < 0) {\n> >>                                       switch (errno) {\n> >>                                       case EAGAIN:\n> >> @@ -915,7 +922,7 @@ static int service_loop(struct socketlist *socklist)\n> >>                                               die_errno(\"accept returned\");\n> >>                                       }\n> >>                               }\n> >> -                             handle(incoming, (struct sockaddr *)&ss, sslen);\n> >> +                             handle(incoming, &ss.sa, sslen);\n> >>                       }\n> >>               }\n> >>       }\n> >\n> > As you say yourself, it's not elegant at all - sockaddr_storage is\n> > intended to be just that, an struct large enough to fit all the sockaddrs\n> > you'll encounter on this platform, with all fields aligned in the same way\n> > as all the other sockaddr structs. You're supposed to be able to cast the\n> > sockaddr struct pointers like currently is done, although I'm not familiar\n> > with the strict aliasing stuff well enough to know if anything else would\n> > be required somewhere.\n> >\n> \n> Strict aliasing isn't exactly about the structure being large enough\n> or not, it's only being able to access a particular piece of memory\n> through one type only (unless specificly marked with \"union\").\n> sockaddr_storage is an attempt at fixing the storage-problem without\n> addressing the type punning problem, which doesn't help us much.\n\nGiven this, does that mean that all code that uses sockaddr_storage \ndirectly without a union, and casting pointers to this struct into \nsockaddr, sockaddr_in and sockaddr_in6 is incorrect with regards to strict \naliasing?\n\nThat is, even this example from RFC 2553 is faulty:\n\n      struct sockaddr_storage __ss;\n      struct sockaddr_in6 *sin6;\n      sin6 = (struct sockaddr_in6 *) &__ss;\n\n> > I didn't see any of these hacks in the v7 patchset - did the warning go\n> > away by itself there?\n> >\n> \n> The strict aliasing problem was (as I described earlier, and you\n> pointed out later in your email) already present in the code. All the\n> patch did, was modify the code enough to make GCC realize it.\n> \n> Since the code is removed by a later patch (\"daemon: get remote host\n> address from root-process\"), I figured adding a union just to remove\n> it was just noisy. So instead I changed the code enough for the\n> warning to go away again. It turned out that it was the assignment of\n> NULL to \"peer\" that triggered the warning, so I made two calls to\n> execute() instead, one that pass NULL and one that pass \"peer\".\n> \n> Then in \"daemon: get remote host address from root-process\" which\n> causes a similar strict-aliasing issue (this time I'm the one who\n> introduced it, since the handle() code-path doesn't derefence \"addr\"),\n> I fixed it with a union.\n\nAh, I didn't see that one. Ok, that explains it.\n\nThe union solution is correct although not pretty, while the one changing \nit to a bare sockaddr was wrong, which was what caught my attention. :-)\n\n> So a nice end-result of v7 is that we're good with strict aliasing,\n> which means that it's not safe(er) to compile git-daemon on GCC with\n> -O3.\n\nActually, couldn't there still be similar strict aliasing violations left \nthat GCC hasn't realized yet?\n\n// Martin"},{"id":"155156","messageId":"AANLkTik=hwAmB4Ha74pqgR-cDW87GnATEpfVFDCfEHks@mail.gmail.com","threadId":"25629","inReplyTo":"alpine.DEB.2.00.1011041118200.31519@cone.home.martin.st","subject":"Re: [PATCH v6 00/16] daemon-win32","fromName":"Erik Faye-Lund","fromEmail":"kusmabite@gmail.com","sentAt":"2010-11-04T10:15:05Z","receivedAt":"2010-11-04T10:15:05Z","isPatch":true,"sender":{"key":"kusmabite@gmail.com","avatar":"https://avatars.githubusercontent.com/u/47073?v=4"},"body":"On Thu, Nov 4, 2010 at 10:35 AM, Martin Storsjö <martin@martin.st> wrote:\n> On Thu, 4 Nov 2010, Erik Faye-Lund wrote:\n>\n>> On Thu, Nov 4, 2010 at 9:58 AM, Martin Storsjö <martin@martin.st> wrote:\n>> > On Thu, 4 Nov 2010, Erik Faye-Lund wrote:\n>> >\n>> >> On Thu, Nov 4, 2010 at 1:06 AM, Erik Faye-Lund <kusmabite@gmail.com> wrote:\n>> >> >\n>> >> > Stuffing all of sockaddr, sockaddr_in and sockaddr_in6 (when built\n>> >> > with IPv6 support) in a union and passing that around instead does\n>> >> > seem to fix the issue completely. I don't find it very elegant, but\n>> >> > some google-searches on the issue seems to reveal that this is the\n>> >> > only way of getting rid of this. Any other suggestions, people?\n>> >> >\n>> >>\n>> >> Just for reference, this is the patch that fixes it. What do you think?\n>> >>\n>> >> diff --git a/daemon.c b/daemon.c\n>> >> index 941c095..8162f10 100644\n>> >> --- a/daemon.c\n>> >> +++ b/daemon.c\n>> >> @@ -902,9 +903,15 @@ static int service_loop(struct socketlist *socklist)\n>> >>\n>> >>               for (i = 0; i < socklist->nr; i++) {\n>> >>                       if (pfd[i].revents & POLLIN) {\n>> >> -                             struct sockaddr_storage ss;\n>> >> +                             union {\n>> >> +                                     struct sockaddr sa;\n>> >> +                                     struct sockaddr_in sai;\n>> >> +#ifndef NO_IPV6\n>> >> +                                     struct sockaddr_in6 sai6;\n>> >> +#endif\n>> >> +                             } ss;\n>> >>                               unsigned int sslen = sizeof(ss);\n>> >> -                             int incoming = accept(pfd[i].fd, (struct sockaddr *)&ss, &sslen);\n>> >> +                             int incoming = accept(pfd[i].fd, &ss.sa, &sslen);\n>> >>                               if (incoming < 0) {\n>> >>                                       switch (errno) {\n>> >>                                       case EAGAIN:\n>> >> @@ -915,7 +922,7 @@ static int service_loop(struct socketlist *socklist)\n>> >>                                               die_errno(\"accept returned\");\n>> >>                                       }\n>> >>                               }\n>> >> -                             handle(incoming, (struct sockaddr *)&ss, sslen);\n>> >> +                             handle(incoming, &ss.sa, sslen);\n>> >>                       }\n>> >>               }\n>> >>       }\n>> >\n>> > As you say yourself, it's not elegant at all - sockaddr_storage is\n>> > intended to be just that, an struct large enough to fit all the sockaddrs\n>> > you'll encounter on this platform, with all fields aligned in the same way\n>> > as all the other sockaddr structs. You're supposed to be able to cast the\n>> > sockaddr struct pointers like currently is done, although I'm not familiar\n>> > with the strict aliasing stuff well enough to know if anything else would\n>> > be required somewhere.\n>> >\n>>\n>> Strict aliasing isn't exactly about the structure being large enough\n>> or not, it's only being able to access a particular piece of memory\n>> through one type only (unless specificly marked with \"union\").\n>> sockaddr_storage is an attempt at fixing the storage-problem without\n>> addressing the type punning problem, which doesn't help us much.\n>\n> Given this, does that mean that all code that uses sockaddr_storage\n> directly without a union, and casting pointers to this struct into\n> sockaddr, sockaddr_in and sockaddr_in6 is incorrect with regards to strict\n> aliasing?\n>\n> That is, even this example from RFC 2553 is faulty:\n>\n>      struct sockaddr_storage __ss;\n>      struct sockaddr_in6 *sin6;\n>      sin6 = (struct sockaddr_in6 *) &__ss;\n>\n\nYes, at least with C99. Section 6.5, paragraph 7 of the C99 specification says:\n\n\"An object shall have its stored value accessed only by an lvalue\nexpression that has one of\nthe following types:\n\n- a type compatible with the effective type of the object,\n- a qualiﬁed version of a type compatible with the effective type of the object,\n- a type that is the signed or unsigned type corresponding to the\neffective type of the\nobject,\n- a type that is the signed or unsigned type corresponding to a\nqualiﬁed version of the\neffective type of the object,\n- an aggregate or union type that includes one of the aforementioned\ntypes among its\nmembers (including, recursively,amember of a subaggregate or contained\nunion), or\n- a character type.\"\n\nA type punned pointer does not meet any of those requirements.\n\nFor pre-C99 I don't have any reference other than Wikpedia, which\nindicates that it's illegal in the ISO version of the standard (which\nI assume must be C90):\n\n\"To enable such optimizations in a predictable manner, the ISO\nstandard for the C programming language (including its newer C99\nedition, see section 6.5, paragraph 7) specifies that it is illegal\n(with some exceptions) for pointers of different types to reference\nthe same memory location.\"\n\nref: http://en.wikipedia.org/wiki/Aliasing_(computing)\n\nBut the code above is incorrect in another sense: it's declaring a\nsymbol with a name starting with double underscore, something that is\nreserved for the compiler. So I don't think I would trust the person\nwho wrote it to care much about standards compliance.\n"}]}