--- bsd-cygwin_util.c.in Fri Dec 28 22:08:30 2001 +++ bsd-cygwin_util.c Wed Apr 24 23:41:54 2002 @@ -163,4 +163,63 @@ RegisterServiceProcess(0, 1); } +/* This is a part of a workaround for the following Microsft bug + on Win95/98/Me: + http://support.microsoft.com/default.aspx?scid=kb;en-us;Q198663 + http://support.microsoft.com/default.aspx?scid=kb;EN-US;q229658 + + msbug_close(pid, fd) is normally called twice. + The first time fd is >= 0. + On Win95/98/Me it then records the fd as belonging to the pid, + instead of closing it outright, and it sets the + "close on fork" flag to avoid further duplications. + The function is called again with fd < 0 when the pid exits. + It then closes the associated fd. + The two calls can safely be made in different threads. + + The function returns the value of the fcntl() or close() call + it makes, if any, else 0. +*/ +#include +#include +#include "log.h" +#define msbug_MAXFD 128 /* Plenty for small systems */ +int msbug_close(pid_t pid, int fd) +{ + int i; + static struct { + pid_t pid; + int fd; + } info[msbug_MAXFD] = {}; + + if (GetVersion() < 0x80000000) { + if (fd >= 0) return close(fd); + else return 0; + } + if (fd >= 0) { + for (i = 0; i < msbug_MAXFD; i++){ + if (info[i].pid == 0) { + info[i].fd = fd; + info[i].pid = pid; /* Done last */ + return fcntl(fd, F_SETCF, 0); + } + } + return close(fd); /* Better now than never */ + } + else { + struct linger linger = {}; + for (i = 0; i < msbug_MAXFD; i++){ + if (info[i].pid == pid) { + fd = info[i].fd; + info[i].pid = 0; /* Done last */ + fcntl(fd, F_SETFL, 0); /* Blocking */ + setsockopt(fd, SOL_SOCKET, SO_LINGER, + &linger, sizeof(linger)); + return close(fd); + } + } + error("could not find pid %d", pid); + return 0; + } +} #endif /* HAVE_CYGWIN */