--------------------- PatchSet 3676 Date: 2006/09/03 16:51:20 Author: serassio Branch: nt Tag: (none) Log: Drop IPC refactored support (moved to ipc branch) an forward port latest 2.6 changes Members: configure.in:1.26.2.97->1.26.2.98 src/Makefile.am:1.26.2.87->1.26.2.88 src/defines.h:1.6.2.9->1.6.2.10 src/dns.cc:1.5.2.8->1.5.2.9 src/external_acl.cc:1.14.2.37->1.14.2.38 src/helper.cc:1.10.2.19->1.10.2.20 src/icmp.cc:1.7.2.8->1.7.2.9 src/ipc.cc:1.8.2.21->1.8.2.22 src/ipc.h:1.1.18.1->1.1.18.2(DEAD) src/ipc_win32.cc:1.1->1.1.2.1 src/protos.h:1.19.2.58->1.19.2.59 src/redirect.cc:1.5.2.17->1.5.2.18 src/unlinkd.cc:1.7.2.10->1.7.2.11 src/DiskIO/DiskDaemon/DiskdIOStrategy.cc:1.1.2.3->1.1.2.4 Index: squid3/configure.in =================================================================== RCS file: /cvsroot/squid-sf//squid3/configure.in,v retrieving revision 1.26.2.97 retrieving revision 1.26.2.98 diff -u -r1.26.2.97 -r1.26.2.98 --- squid3/configure.in 3 Sep 2006 08:44:13 -0000 1.26.2.97 +++ squid3/configure.in 3 Sep 2006 16:51:20 -0000 1.26.2.98 @@ -1,7 +1,7 @@ dnl Configuration input file for Squid dnl -dnl $Id: configure.in,v 1.26.2.97 2006/09/03 08:44:13 serassio Exp $ +dnl $Id: configure.in,v 1.26.2.98 2006/09/03 16:51:20 serassio Exp $ dnl dnl dnl @@ -11,7 +11,7 @@ AC_CONFIG_AUX_DIR(cfgaux) AC_CONFIG_SRCDIR([src/main.cc]) AM_INIT_AUTOMAKE([tar-ustar]) -AC_REVISION($Revision: 1.26.2.97 $)dnl +AC_REVISION($Revision: 1.26.2.98 $)dnl AC_PREFIX_DEFAULT(/usr/local/squid) AM_MAINTAINER_MODE @@ -75,8 +75,12 @@ LIBS="$LIBS -lpsapi" fi MINGW_LIBS="-lmingwex" + AM_CONDITIONAL(USE_IPC_WIN32, true) AC_SUBST(MINGW_LIBS) ;; +*) + AM_CONDITIONAL(USE_IPC_WIN32, false) + ;; esac if test -z "$CACHE_HTTP_PORT"; then Index: squid3/src/Makefile.am =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/Makefile.am,v retrieving revision 1.26.2.87 retrieving revision 1.26.2.88 diff -u -r1.26.2.87 -r1.26.2.88 --- squid3/src/Makefile.am 2 Sep 2006 20:07:09 -0000 1.26.2.87 +++ squid3/src/Makefile.am 3 Sep 2006 16:51:22 -0000 1.26.2.88 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.am,v 1.26.2.87 2006/09/02 20:07:09 serassio Exp $ +# $Id: Makefile.am,v 1.26.2.88 2006/09/03 16:51:22 serassio Exp $ # # Uncomment and customize the following to suit your needs: # @@ -147,6 +147,12 @@ WIN32_SOURCE = endif +if USE_IPC_WIN32 +IPC_SOURCE = ipc_win32.cc +else +IPC_SOURCE = ipc.cc +endif + IDENT_ALL_SOURCE = ACLIdent.cc ACLIdent.h ident.cc if ENABLE_IDENT IDENT_SOURCE = $(IDENT_ALL_SOURCE) @@ -254,6 +260,8 @@ dnsserver.cc \ dns_internal.cc \ htcp.cc \ + ipc.cc \ + ipc_win32.cc \ htcp.h \ $(IDENT_ALL_SOURCE) \ $(ESI_ALL_SOURCE) \ @@ -485,8 +493,7 @@ $(IDENT_SOURCE) \ int.cc \ internal.cc \ - ipc.cc \ - ipc.h \ + $(IPC_SOURCE) \ ipcache.cc \ $(LEAKFINDERSOURCE) \ list.cc \ @@ -782,7 +789,7 @@ icp_v3.cc \ $(IDENT_SOURCE) \ internal.cc \ - ipc.cc \ + $(IPC_SOURCE) \ ipcache.cc \ $(LEAKFINDERSOURCE) \ list.cc \ @@ -1289,7 +1296,7 @@ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ - ipc.cc \ + $(IPC_SOURCE) \ ipcache.cc \ int.cc \ internal.cc \ @@ -1440,7 +1447,7 @@ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ - ipc.cc \ + $(IPC_SOURCE) \ ipcache.cc \ int.cc \ internal.cc \ @@ -1590,7 +1597,7 @@ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ - ipc.cc \ + $(IPC_SOURCE) \ ipcache.cc \ int.cc \ internal.cc \ @@ -1770,7 +1777,7 @@ $(IDENT_SOURCE) \ int.cc \ internal.cc \ - ipc.cc \ + $(IPC_SOURCE) \ ipcache.cc \ list.cc \ logfile.cc \ @@ -1918,7 +1925,7 @@ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ - ipc.cc \ + $(IPC_SOURCE) \ ipcache.cc \ int.cc \ internal.cc \ @@ -2251,7 +2258,7 @@ icp_v2.cc \ icp_v3.cc \ $(IDENT_SOURCE) \ - ipc.cc \ + $(IPC_SOURCE) \ ipcache.cc \ int.cc \ internal.cc \ Index: squid3/src/defines.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/defines.h,v retrieving revision 1.6.2.9 retrieving revision 1.6.2.10 diff -u -r1.6.2.9 -r1.6.2.10 --- squid3/src/defines.h 22 Aug 2006 10:26:04 -0000 1.6.2.9 +++ squid3/src/defines.h 3 Sep 2006 16:51:23 -0000 1.6.2.10 @@ -1,6 +1,6 @@ /* - * $Id: defines.h,v 1.6.2.9 2006/08/22 10:26:04 serassio Exp $ + * $Id: defines.h,v 1.6.2.10 2006/09/03 16:51:23 serassio Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -180,6 +180,21 @@ #define STORE_META_DIRTY 0x04 #define STORE_META_BAD 0x05 +#define IPC_NONE 0 +#define IPC_TCP_SOCKET 1 +#define IPC_UDP_SOCKET 2 +#define IPC_FIFO 3 +#define IPC_UNIX_STREAM 4 +#define IPC_UNIX_DGRAM 5 + +#if HAVE_SOCKETPAIR && defined (AF_UNIX) +#define IPC_STREAM IPC_UNIX_STREAM +#define IPC_DGRAM IPC_UNIX_DGRAM +#else +#define IPC_STREAM IPC_TCP_SOCKET +#define IPC_DGRAM IPC_UDP_SOCKET +#endif + #define STORE_META_KEY STORE_META_KEY_MD5 #define STORE_META_TLD_START sizeof(int)+sizeof(char) Index: squid3/src/dns.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/dns.cc,v retrieving revision 1.5.2.8 retrieving revision 1.5.2.9 diff -u -r1.5.2.8 -r1.5.2.9 --- squid3/src/dns.cc 31 May 2006 21:17:02 -0000 1.5.2.8 +++ squid3/src/dns.cc 3 Sep 2006 16:51:23 -0000 1.5.2.9 @@ -1,6 +1,6 @@ /* - * $Id: dns.cc,v 1.5.2.8 2006/05/31 21:17:02 serassio Exp $ + * $Id: dns.cc,v 1.5.2.9 2006/09/03 16:51:23 serassio Exp $ * * DEBUG: section 34 Dnsserver interface * AUTHOR: Harvest Derived @@ -45,9 +45,6 @@ */ #if USE_DNSSERVERS -/* For the IPC type defines */ -#include "ipc.h" - static helper *dnsservers = NULL; static void Index: squid3/src/external_acl.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/external_acl.cc,v retrieving revision 1.14.2.37 retrieving revision 1.14.2.38 diff -u -r1.14.2.37 -r1.14.2.38 --- squid3/src/external_acl.cc 22 Aug 2006 10:26:04 -0000 1.14.2.37 +++ squid3/src/external_acl.cc 3 Sep 2006 16:51:23 -0000 1.14.2.38 @@ -1,6 +1,6 @@ /* - * $Id: external_acl.cc,v 1.14.2.37 2006/08/22 10:26:04 serassio Exp $ + * $Id: external_acl.cc,v 1.14.2.38 2006/09/03 16:51:23 serassio Exp $ * * DEBUG: section 82 External ACL * AUTHOR: Henrik Nordstrom, MARA Systems AB @@ -47,7 +47,6 @@ #include "AuthUserRequest.h" #include "SquidTime.h" #include "Store.h" -#include "ipc.h" #include "fde.h" #include "ACLChecklist.h" #include "ACL.h" Index: squid3/src/helper.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/helper.cc,v retrieving revision 1.10.2.19 retrieving revision 1.10.2.20 diff -u -r1.10.2.19 -r1.10.2.20 --- squid3/src/helper.cc 22 Aug 2006 10:26:05 -0000 1.10.2.19 +++ squid3/src/helper.cc 3 Sep 2006 16:51:26 -0000 1.10.2.20 @@ -1,6 +1,6 @@ /* - * $Id: helper.cc,v 1.10.2.19 2006/08/22 10:26:05 serassio Exp $ + * $Id: helper.cc,v 1.10.2.20 2006/09/03 16:51:26 serassio Exp $ * * DEBUG: section 84 Helper process maintenance * AUTHOR: Harvest Derived? @@ -39,7 +39,6 @@ #include "Store.h" #include "comm.h" #include "MemBuf.h" -#include "ipc.h" #include "wordlist.h" #define HELPER_MAX_ARGS 64 @@ -81,6 +80,10 @@ helper_server *srv; int nargs = 0; int k; + pid_t pid; + int rfd; + int wfd; + void * hIpc; wordlist *w; if (hlp->cmdline == NULL) @@ -111,12 +114,16 @@ for (k = 0; k < hlp->n_to_start; k++) { getCurrentTime(); - IPCResult ipcRV = ipcCreate(hlp->ipc_type, - progname, - args, - shortname); + rfd = wfd = -1; + pid = ipcCreate(hlp->ipc_type, + progname, + args, + shortname, + &rfd, + &wfd, + &hIpc); - if (!ipcRV.success) { + if (pid < 0) { debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname); continue; } @@ -125,15 +132,11 @@ hlp->n_active++; CBDATA_INIT_TYPE(helper_server); srv = cbdataAlloc(helper_server); -#ifdef _SQUID_MSWIN_ - - srv->hIpc = ipcRV.hIpc; -#endif - - srv->pid = ipcRV.pid; + srv->hIpc = hIpc; + srv->pid = pid; srv->index = k; - srv->rfd = ipcRV.rfd; - srv->wfd = ipcRV.wfd; + srv->rfd = rfd; + srv->wfd = wfd; srv->rbuf = (char *)memAllocBuf(8192, &srv->rbuf_sz); srv->wqueue = new MemBuf; srv->roffset = 0; @@ -141,22 +144,22 @@ srv->parent = cbdataReference(hlp); dlinkAddTail(srv, &srv->link, &hlp->servers); - if (srv->rfd == srv->wfd) { + if (rfd == wfd) { snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d", shortname, k + 1); - fd_note(srv->rfd, fd_note_buf); + fd_note(rfd, fd_note_buf); } else { snprintf(fd_note_buf, FD_DESC_SZ, "reading %s #%d", shortname, k + 1); - fd_note(srv->rfd, fd_note_buf); + fd_note(rfd, fd_note_buf); snprintf(fd_note_buf, FD_DESC_SZ, "writing %s #%d", shortname, k + 1); - fd_note(srv->wfd, fd_note_buf); + fd_note(wfd, fd_note_buf); } - commSetNonBlocking(srv->rfd); + commSetNonBlocking(rfd); - if (srv->wfd != srv->rfd) - commSetNonBlocking(srv->wfd); + if (wfd != rfd) + commSetNonBlocking(wfd); - comm_add_close_handler(srv->rfd, helperServerFree, srv); + comm_add_close_handler(rfd, helperServerFree, srv); comm_read(srv->rfd, srv->rbuf, srv->rbuf_sz - 1, helperHandleRead, srv); } @@ -179,6 +182,10 @@ helper_stateful_server *srv; int nargs = 0; int k; + pid_t pid; + int rfd; + int wfd; + void * hIpc; wordlist *w; if (hlp->cmdline == NULL) @@ -209,12 +216,16 @@ for (k = 0; k < hlp->n_to_start; k++) { getCurrentTime(); - IPCResult ipcRV = ipcCreate(hlp->ipc_type, - progname, - args, - shortname); + rfd = wfd = -1; + pid = ipcCreate(hlp->ipc_type, + progname, + args, + shortname, + &rfd, + &wfd, + &hIpc); - if (!ipcRV.success) { + if (pid < 0) { debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname); continue; } @@ -223,12 +234,8 @@ hlp->n_active++; CBDATA_INIT_TYPE(helper_stateful_server); srv = cbdataAlloc(helper_stateful_server); -#ifdef _SQUID_MSWIN_ - - srv->hIpc = ipcRV.hIpc; -#endif - - srv->pid = ipcRV.pid; + srv->hIpc = hIpc; + srv->pid = pid; srv->flags.reserved = S_HELPER_FREE; srv->deferred_requests = 0; srv->stats.deferbyfunc = 0; @@ -236,9 +243,9 @@ srv->stats.submits = 0; srv->stats.releases = 0; srv->index = k; - srv->rfd = ipcRV.rfd; - srv->wfd = ipcRV.wfd; - srv->rbuf = (char *)memAllocBuf(8192, &srv->rbuf_sz); + srv->rfd = rfd; + srv->wfd = wfd; + srv->rbuf = (char *)memAllocBuf(8192, &srv->rbuf_sz); srv->roffset = 0; srv->parent = cbdataReference(hlp); @@ -247,22 +254,22 @@ dlinkAddTail(srv, &srv->link, &hlp->servers); - if (srv->rfd == srv->wfd) { + if (rfd == wfd) { snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d", shortname, k + 1); - fd_note(srv->rfd, fd_note_buf); + fd_note(rfd, fd_note_buf); } else { snprintf(fd_note_buf, FD_DESC_SZ, "reading %s #%d", shortname, k + 1); - fd_note(srv->rfd, fd_note_buf); + fd_note(rfd, fd_note_buf); snprintf(fd_note_buf, FD_DESC_SZ, "writing %s #%d", shortname, k + 1); - fd_note(srv->wfd, fd_note_buf); + fd_note(wfd, fd_note_buf); } - commSetNonBlocking(srv->rfd); + commSetNonBlocking(rfd); - if (srv->wfd != srv->rfd) - commSetNonBlocking(srv->wfd); + if (wfd != rfd) + commSetNonBlocking(wfd); - comm_add_close_handler(srv->rfd, helperStatefulServerFree, srv); + comm_add_close_handler(rfd, helperStatefulServerFree, srv); comm_read(srv->rfd, srv->rbuf, srv->rbuf_sz - 1, helperStatefulHandleRead, srv); Index: squid3/src/icmp.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/icmp.cc,v retrieving revision 1.7.2.8 retrieving revision 1.7.2.9 diff -u -r1.7.2.8 -r1.7.2.9 --- squid3/src/icmp.cc 2 Sep 2006 16:02:52 -0000 1.7.2.8 +++ squid3/src/icmp.cc 3 Sep 2006 16:51:26 -0000 1.7.2.9 @@ -1,6 +1,6 @@ /* - * $Id: icmp.cc,v 1.7.2.8 2006/09/02 16:02:52 serassio Exp $ + * $Id: icmp.cc,v 1.7.2.9 2006/09/03 16:51:26 serassio Exp $ * * DEBUG: section 37 ICMP Routines * AUTHOR: Duane Wessels @@ -36,7 +36,6 @@ #include "squid.h" #include "comm.h" -#include "ipc.h" #if USE_ICMP @@ -53,9 +52,7 @@ static void icmpHandleSourcePing(const struct sockaddr_in *from, const char *buf); #endif -#ifdef _SQUID_MSWIN_ -static HANDLE hIpc; -#endif +static void * hIpc; static pid_t pid; static void @@ -252,6 +249,8 @@ { #if USE_ICMP const char *args[2]; + int rfd; + int wfd; if (strcmp(Config.Program.pinger, "none") == 0) { debug(37, 1) ("Pinger disabled\n"); @@ -260,25 +259,20 @@ args[0] = "(pinger)"; args[1] = NULL; - IPCResult ipcRV = ipcCreate(IPC_DGRAM, - Config.Program.pinger, - args, - "Pinger Socket"); + pid = ipcCreate(IPC_DGRAM, + Config.Program.pinger, + args, + "Pinger Socket", + &rfd, + &wfd, + &hIpc); - if (!ipcRV.success) + if (pid < 0) return; -#ifdef _SQUID_MSWIN_ - - hIpc = ipcRV.hIpc; - - pid = ipcRV.pid; - -#endif - - assert(ipcRV.rfd == ipcRV.wfd); + assert(rfd == wfd); - icmp_sock = ipcRV.rfd; + icmp_sock = rfd; fd_note(icmp_sock, "pinger"); Index: squid3/src/ipc.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/ipc.cc,v retrieving revision 1.8.2.21 retrieving revision 1.8.2.22 diff -u -r1.8.2.21 -r1.8.2.22 --- squid3/src/ipc.cc 14 May 2006 17:11:06 -0000 1.8.2.21 +++ squid3/src/ipc.cc 3 Sep 2006 16:51:26 -0000 1.8.2.22 @@ -1,6 +1,6 @@ /* - * $Id: ipc.cc,v 1.8.2.21 2006/05/14 17:11:06 serassio Exp $ + * $Id: ipc.cc,v 1.8.2.22 2006/09/03 16:51:26 serassio Exp $ * * DEBUG: section 54 Interprocess Communication * AUTHOR: Duane Wessels @@ -34,1400 +34,252 @@ */ #include "squid.h" -#include "ipc.h" #include "comm.h" #include "fde.h" -#include "SquidTime.h" - -#ifdef _SQUID_MSWIN_ -#ifndef _MSWSOCK_ -#include -#endif -#include -#endif - -class FDPair -{ - -public: - FDPair() : rfd (-1), wfd (-1) {} - - FDPair (int anFD) : rfd (anFD), wfd (anFD) {} - - FDPair (int r, int w) : rfd (r), wfd (w) {} - - void close(); - int rfd; - int wfd; -}; - - -/* XXX: The mechanics could be made into a strategy and this - class a parent for classes that need to spawn. - For now, a callforward will do. Alternatively we could - make this a template class and use a unary functor. - */ - -class Spawn -{ - -public: - static Spawn *GetSpawn(); - virtual ~Spawn(){} - - virtual Spawn *clone() const = 0; - virtual bool success() const = 0; - /* For windows, until the spawn object is kept around */ - virtual void * getHandle() const = 0; - virtual pid_t getPid() const = 0; - typedef unsigned int Child (void *); - virtual void splitExecution(Child*, void *) = 0; - // virtual ... startProcess(prog, args); - -protected: - Spawn (){} - - Spawn (Spawn const &){} - - Spawn &operator= (Spawn const &); - -private: -}; - -#ifdef _SQUID_MSWIN_ - -class WindowsSpawn : public Spawn -{ - -public: - WindowsSpawn(); - virtual Spawn *clone() const; - virtual bool success() const; - /* For windows, until the spawn object is kept around */ - virtual void * getHandle() const; - virtual pid_t getPid() const; - virtual void splitExecution(Child*, void *); - ~WindowsSpawn(); - -protected: - WindowsSpawn (WindowsSpawn const &); - WindowsSpawn &operator= (WindowsSpawn const &); - -private: - static unsigned int __stdcall ThreadReflector (void *); - Child* newThread; - void *data; - pid_t pid; - int error; - unsigned int childRV; - unsigned threadID; - void * threadHandle; -}; - -#else - -class UnixSpawn : public Spawn -{ - -public: - UnixSpawn(); - virtual Spawn *clone() const; - virtual bool success() const; - /* For windows, until the spawn object is kept around */ - virtual void * getHandle() const; - virtual pid_t getPid() const; - virtual void splitExecution(Child*, void *); - -protected: - UnixSpawn (UnixSpawn const &); - UnixSpawn &operator= (UnixSpawn const &); - -private: - void child(); - Child* newThread; - void *data; - pid_t pid; -}; - -#endif - -Spawn * -Spawn::GetSpawn() -{ -#ifdef _SQUID_MSWIN_ - return new WindowsSpawn; -#else - - return new UnixSpawn; -#endif -} - -class IPC -{ - -public: - static IPC *Create(int type, const char *prog, const char *const args[], const char *name); - static unsigned int ForkChild(void *); - IPCResult result() const { return rv;} - - virtual ~IPC() - { - safe_free (name_); - delete mySpawn; - } - - virtual IPC *clone() const = 0; - - /* FIXME: move below again */ - - FDPair childFD; - - virtual struct sockaddr_in & PS (); - Spawn *mySpawn; - const char *prog; - char * const *args; - virtual void childFDConnect(); - virtual bool childFDConnected() const; - virtual int childWrite(char const *, size_t) = 0; - void doExec(); - -protected: - IPC (char const *aName); - IPC(IPC const &); - - /* not implemented, but the synthetic operator won't do */ - IPC &operator= (IPC const &); - - void result (IPCResult const& newRV) - { - rv = newRV; - } - - char const *name() const {return name_;} - - virtual void markFailed(); - virtual void cleanUp(); - virtual bool openedInitialFDs() const; - - virtual struct sockaddr_in & CS (); - // virtual struct sockaddr_in & PS (); - virtual void prepFDsForSpawn(); - virtual bool preppedFDsForSpawn() const; - // virtual void childFDConnect(); - // virtual bool childFDConnected() const; - int prfd; - int pwfd; - static IPC *Factory(int type, char const *name); - -private: - IPC (IPCResult aResult):rv(aResult){} - - void closeAllFD(); - IPCResult rv; - char const *name_; -}; - -#ifndef _SQUID_MSWIN_ -#if ! (HAVE_POLL && defined(_SQUID_OSF_)) - -class IPCFIFO : public IPC -{ - -public: - virtual IPC *clone() const; - virtual int childWrite(char const *, size_t); - -private: - friend IPC *IPC::Factory(int, char const *); - IPCFIFO (char const *aName); -}; - -IPCFIFO::IPCFIFO (char const *aName) : IPC(aName) -{ - int p2c[2]; - int c2p[2]; - - if (pipe(p2c) < 0) { - debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror()); - return; - } - - if (pipe(c2p) < 0) { - debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror()); - return; - } - - childFD = FDPair (c2p[0], p2c[1]); - fdc_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read"); - fdc_open(childFD.wfd, FD_PIPE, "IPC FIFO Child Write"); - fdc_open(childFD.rfd, FD_PIPE, "IPC FIFO Child Read"); - fdc_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write"); -} - -IPC * -IPCFIFO::clone() const -{ - IPCFIFO *rv = new IPCFIFO (*this); - return rv; -} - -int -IPCFIFO::childWrite(char const *buf , size_t len) -{ - int result = write(childFD.wfd, buf, len); - - if (result < 0) - debug(50, 0) ("write FD %d: %s\n", childFD.wfd, xstrerror()); - - return result; -} - -#endif -#endif - -class IPCSocket : public IPC -{ - -public: - virtual IPC *clone() const = 0; - -protected: - IPCSocket (char const *aName, int socktype, int proto); - IPCSocket (IPCSocket const &); - /* not implemented */ - IPCSocket &operator=(IPCSocket const &); - - virtual struct sockaddr_in & CS (); - - virtual struct sockaddr_in & PS (); - virtual void prepFDsForSpawn(); - virtual bool preppedFDsForSpawn() const; - bool fdDetailsRetrieved; - -private: - int openASocket(int socktype, int proto, int flags) const; - - struct sockaddr_in CS_; - - struct sockaddr_in PS_; -}; - -IPCSocket::IPCSocket (char const *aName, int socktype, int proto) : IPC (aName), - fdDetailsRetrieved (false) -{ -#ifdef _SQUID_MSWIN_ /* Windows IPC needs Overlapped sockets */ - int opt = 0; - int optlen = sizeof(opt); - - if (WIN32_OS_version !=_WIN_OS_WINNT) { - getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen); - opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT); - setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, sizeof(opt)); - } - -#endif - - childFD = FDPair (openASocket (socktype, proto, COMM_NOCLOEXEC)); - - prfd = pwfd = openASocket (socktype, proto, 0); /* blocking */ - -#ifdef _SQUID_MSWIN_ /* Restore sockets to synchronous mode*/ - - if (WIN32_OS_version !=_WIN_OS_WINNT) { - getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen); - opt = opt | SO_SYNCHRONOUS_NONALERT; - setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen); - } - -#endif - -} - -IPCSocket::IPCSocket (IPCSocket const &old) : IPC(old), fdDetailsRetrieved (old.fdDetailsRetrieved), - CS_(old.CS_), PS_(old.PS_) -{} - -struct sockaddr_in & - IPCSocket::CS() -{ - return CS_; -} - -struct sockaddr_in & - IPCSocket::PS() -{ - return PS_; -} - -void -IPCSocket::prepFDsForSpawn() -{ - socklen_t len = sizeof(PS_); - memset(&PS_, '\0', len); - - if (getsockname(pwfd, (struct sockaddr *) &PS_, &len) < 0) { - debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); - return; - } - - debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", - pwfd, inet_ntoa(PS_.sin_addr), ntohs(PS_.sin_port)); - len = sizeof(CS_); - memset(&CS_, '\0', len); - - if (getsockname(childFD.rfd, (struct sockaddr *) &CS_, &len) < 0) { - debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); - return; - } - - debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", - childFD.rfd, inet_ntoa(CS_.sin_addr), ntohs(CS_.sin_port)); - - fdDetailsRetrieved = true; -} - -bool -IPCSocket::preppedFDsForSpawn() const -{ - return fdDetailsRetrieved; -} - -int -IPCSocket::openASocket(int socktype, int proto, int flags) const -{ - return comm_open(socktype, - proto, /* protocol */ - local_addr, - 0, /* port */ - flags, /* blocking */ - name()); -} - -class IPCTCP : public IPCSocket -{ - -public: - virtual void prepFDsForSpawn(); - virtual bool preppedFDsForSpawn() const; - virtual IPC *clone() const; - virtual int childWrite(char const *, size_t); - -protected: - virtual void childFDConnect(); - virtual bool childFDConnected() const; - -private: - friend IPC *IPC::Factory(int, char const *); - IPCTCP (char const *aName); - bool childConnected; -}; - -IPCTCP::IPCTCP (char const *aName) : - IPCSocket(aName, SOCK_STREAM, IPPROTO_TCP) , childConnected(false) -{} - -void -IPCTCP::prepFDsForSpawn() -{ - IPCSocket::prepFDsForSpawn(); - - if (!IPCSocket::preppedFDsForSpawn()) - return; - - if (listen(childFD.rfd, 1) < 0) { - debug(50, 1) ("ipcCreate: listen FD %d: %s\n", childFD.rfd, xstrerror()); - /* Naughty abstraction break ! */ - fdDetailsRetrieved = false; - return; - } - - debug(54, 3) ("ipcCreate: FD %d listening...\n", childFD.rfd); -} - -bool -IPCTCP::preppedFDsForSpawn() const -{ - /* TODO: heal the abstraction - call this if our flag is ok, otherwise - * return false. (See preFDsForSpawn) - */ - return IPCSocket::preppedFDsForSpawn(); -} - -IPC * -IPCTCP::clone() const -{ - IPCTCP *rv = new IPCTCP (*this); - return rv; -} - -void -IPCTCP::childFDConnect() -{ - debug(54, 3) ("ipcCreate: calling accept on FD %d\n", childFD.rfd); - int tempFD; - - if ((tempFD = accept(childFD.rfd, NULL, NULL)) < 0) { - debug(50, 0) ("ipcCreate: FD %d accept: %s\n", childFD.rfd, xstrerror()); - return; - } - - debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", tempFD); - - comm_close(childFD.rfd); -#ifdef _SQUID_MSWIN_ - - char buf1[8192]; - snprintf(buf1, 8191, "%s CHILD socket", prog); - fdc_open(tempFD, FD_SOCKET, buf1); - fd_table[tempFD].flags.ipc = 1; -#endif - - childFD = FDPair (tempFD); - - childConnected = true; -} - -bool -IPCTCP::childFDConnected() const -{ - return childConnected; -} - -int -IPCTCP::childWrite(char const *buf , size_t len) -{ -#ifndef _SQUID_MSWIN_ - int result = write(childFD.wfd, buf, len); - - if (result < 0) - debug(50, 0) ("write FD %d: %s\n", childFD.wfd, xstrerror()); - -#else - - int result = send (childFD.wfd, (const void *) buf, len, 0); - - if (result < 0) - debug(50, 0) ("send FD %d: %s\n", childFD.wfd, xstrerror()); - -#endif - - return result; -} - - -class IPCUDP : public IPCSocket -{ - -public: - virtual IPC *clone() const; - virtual int childWrite(char const *, size_t); - -protected: - virtual void childFDConnect(); - virtual bool childFDConnected() const; - -private: - friend IPC *IPC::Factory(int, char const *); - IPCUDP (char const *aName); - bool childConnected; -}; - -IPCUDP::IPCUDP (char const *aName) : - IPCSocket(aName, SOCK_DGRAM, IPPROTO_UDP), childConnected (false) -{} - -IPC * -IPCUDP::clone() const -{ - IPCUDP *rv = new IPCUDP (*this); - return rv; -} - -void -IPCUDP::childFDConnect() -{ - if (comm_connect_addr(childFD.rfd, &PS()) == COMM_ERROR) - return; - - childConnected = true; -} - -bool -IPCUDP::childFDConnected() const -{ - return childConnected; -} - -int -IPCUDP::childWrite(char const *buf , size_t len) -{ - int result = comm_udp_send(childFD.wfd, buf, len, 0); - - if (result < 0) - debug(50, 0) ("sendto FD %d: %s\n", childFD.wfd, xstrerror()); - - return result; -} - -#if HAVE_SOCKETPAIR && defined(AF_UNIX) -#ifndef _SQUID_MSWIN_ - -class IPCUNIXStream : public IPC -{ - -public: - virtual IPC *clone() const; - virtual int childWrite(char const *, size_t); - -private: - friend IPC *IPC::Factory(int, char const *); - IPCUNIXStream (char const *aName); -}; - -IPCUNIXStream::IPCUNIXStream (char const *aName) : IPC(aName) -{ - int fds[2]; - int buflen = 32768; - - if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { - debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror()); - return; - } - - setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen)); - setsockopt(fds[0], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen)); - setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen)); - setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen)); - childFD = FDPair (fds[1]); - fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX STREAM Parent"); - fdc_open(childFD.rfd, FD_PIPE, "IPC UNIX STREAM Child"); -} - -IPC * -IPCUNIXStream::clone() const -{ - IPCUNIXStream *rv = new IPCUNIXStream (*this); - return rv; -} - -int -IPCUNIXStream::childWrite(char const *buf , size_t len) -{ - int result = write(childFD.wfd, buf, len); - - if (result < 0) - debug(50, 0) ("write FD %d: %s\n", childFD.wfd, xstrerror()); - - return result; -} - -class IPCUNIXDGram : public IPC -{ - -public: - virtual IPC *clone() const; - virtual int childWrite(char const *, size_t); - -private: - friend IPC *IPC::Factory(int, char const *); - IPCUNIXDGram (char const *aName); -}; - -IPCUNIXDGram::IPCUNIXDGram (char const *aName) : IPC(aName) -{ - int fds[2]; - - if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) < 0) { - debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror()); - return; - } - - childFD = FDPair (fds[1]); - fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX DGRAM Parent"); - fdc_open(childFD.rfd, FD_PIPE, "IPC UNIX DGRAM Child"); -} - -IPC * -IPCUNIXDGram::clone() const -{ - IPCUNIXDGram *rv = new IPCUNIXDGram (*this); - return rv; -} - -int -IPCUNIXDGram::childWrite(char const *buf , size_t len) -{ - int result = comm_udp_send(childFD.wfd, buf, len, 0); - - if (result < 0) - debug(50, 0) ("sendto FD %d: %s\n", childFD.wfd, xstrerror()); - - return result; -} - -#endif -#endif - -IPC * -IPC::Factory (int type, char const *name) -{ - if (type == IPC_TCP_SOCKET) - return new IPCTCP (name); - -#ifndef _SQUID_MSWIN_ -#if !(USE_POLL && defined(_SQUID_OSF_)) - - if (type == IPC_FIFO) - return new IPCFIFO (name); - -#endif -#endif - - if (type == IPC_UDP_SOCKET) - return new IPCUDP (name); - -#if HAVE_SOCKETPAIR && defined(AF_UNIX) -#ifndef _SQUID_MSWIN_ - - if (type == IPC_UNIX_STREAM) - return new IPCUNIXStream (name); - - if (type == IPC_UNIX_DGRAM) - return new IPCUNIXDGram (name); - -#endif -#endif - - fatal ("Unexpected IPC type : check your source\n"); - - return NULL; -} - -void -IPC::markFailed() -{ - result(IPCResult(false)); -} - -struct sockaddr_in & - IPC::CS () -{ - fatal("attempt to get Client Socket for non socket IPC class\n"); - - struct sockaddr_in *f = new struct sockaddr_in; - return *f; -} - -struct sockaddr_in & - IPC::PS () -{ - fatal("attempt to get Parent Socket for non socket IPC class\n"); - - struct sockaddr_in *f = new struct sockaddr_in; - return *f; -} - -void -IPC::prepFDsForSpawn() -{} - -bool -IPC::preppedFDsForSpawn() const -{ - return true; -} - -void -IPC::childFDConnect() -{} - -bool -IPC::childFDConnected() const -{ - return true; -} - -class IPCInstance -{ - -public: - static char const *ShutdownMessage; - - IPCInstance(int aType, pid_t aPid, char const *program, int fromChildFD, int toParentFD) : type (aType), - pid(aPid), prog (xstrdup(program)), prfd (fromChildFD), - send_fd (toParentFD){} - - virtual ~IPCInstance() - { - safe_free(prog); - } - - virtual void childToParentLoop(); - -protected: - /* Not implemented */ - IPCInstance(IPCInstance const &); - IPCInstance &operator= (IPCInstance const &); - -private: - /* what sort of IPC we are */ - int const type; - /* if this is really IPC to another process, the process id. */ - pid_t pid; - /* What program it is */ - char *prog; - /* the parent uses this to read from the child */ - int const prfd; - int const send_fd; -}; - -char const *IPCInstance::ShutdownMessage = "$shutdown\n"; - -#ifdef _SQUID_MSWIN_ - -struct ipc_params -{ - static unsigned int ThreadReflector (void *); // ipc_params * - ipc_params (int aType) : type(aType), prfd_ipc (-1), pwfd_ipc(-1), crfd_ipc(-1), cwfd_ipc(-1), - hProcess(NULL), thread(NULL), pid (-1), niceprog(NULL) -#if HAVE_PUTENV - , env_str(NULL) -#endif - { - p2c[0]=-1; - p2c[1]=-1; - c2p[0]=-1; - c2p[1]=-1; - } - ~ipc_params() - { - delete myIPC; - } - - int const type; - const char *prog; - char **args; - IPC *myIPC; - -private: - unsigned int threadLoop(); - void freeResources(); - void normalExit(); - void parentToChildLoop(); - int p2c[2]; - int c2p[2]; - int prfd_ipc, pwfd_ipc, crfd_ipc, cwfd_ipc; - HANDLE hProcess; - HANDLE thread; - pid_t pid; - char *niceprog; - char buf1[8192]; -#if HAVE_PUTENV - - char *env_str; -#endif -}; - -struct thread_params -{ - int type; - int rfd; - int send_fd; - const char *prog; - pid_t pid; -}; - -static unsigned int __stdcall ipc_thread_2(void *); // thread_params * - -static const char *ok_string = "OK\n"; -static const char *err_string = "ERR\n"; -static const char *shutdown_string = "$shutdown\n"; -#endif static const char *hello_string = "hi there\n"; #define HELLO_BUF_SZ 32 -static char hello_buf[HELLO_BUF_SZ]; - -void -FDPair::close() -{ - if (rfd >= 0) - comm_close(rfd); - - if (rfd != wfd && - wfd >= 0) - comm_close (wfd); - - rfd = wfd = -1; -} - -#ifdef _SQUID_MSWIN_ -static void -ipcCloseAllFD(int prfd, int pwfd) -{ - FDPair (prfd, pwfd).close(); -} - -#endif - -static void -PutEnvironment() -{ -#if HAVE_PUTENV - char *env_str; - int tmp_s; - env_str = (char *)xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1); - snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions); - putenv(env_str); -#endif -} - -void -IPC::closeAllFD() -{ - FDPair (prfd, pwfd).close(); - childFD.close(); -} - -void -IPC::cleanUp() -{ - delete mySpawn; - mySpawn = NULL; - closeAllFD(); -} - -void -reserveFD0Thru2(int crfd) -{ - /* - * This double-dup stuff avoids problems when one of - * crfd, cwfd, or debug_log are in the range 0-2. - */ - int openrv; - - do { - /* First make sure 0-2 is occupied by something. Gets cleaned up later */ - openrv = dup(crfd); - assert(openrv > -1); - } while (openrv < 3 && openrv > -1); - - close(openrv); -} - -void -IPC::doExec() -{ -#ifndef _SQUID_MSWIN_ - int t1, t2, t3; - reserveFD0Thru2(childFD.rfd); - t1 = dup(childFD.rfd); - t2 = dup(childFD.wfd); - t3 = dup(fileno(debug_log)); - assert(t1 > 2 && t2 > 2 && t3 > 2); - close(childFD.rfd); - close(childFD.wfd); - close(fileno(debug_log)); - dup2(t1, 0); - dup2(t2, 1); - dup2(t3, 2); - close(t1); - close(t2); - close(t3); - /* Make sure all other filedescriptors are closed */ - - for (int loopIndex = 3; loopIndex < SQUID_MAXFD; ++loopIndex) - close(loopIndex); - - if (opt_no_daemon) { - squid_signal(SIGINT, SIG_IGN, SA_RESETHAND); - squid_signal(SIGHUP, SIG_IGN, SA_RESETHAND); - } - - execvp(prog, (char *const *) args); - - debug_log = fdopen(2, "a+"); - - debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror()); - - _exit(1); - -#else - /* NT code goes here eventually */ -#endif -} - -IPCResult -ipcCreate(int type, const char *prog, const char *const args[], const char *name) -{ - IPC *newIPC = IPC::Create(type, prog, args, name); - IPCResult result = newIPC->result(); - delete newIPC; - return result; -} - -IPC::IPC(char const *aName): mySpawn(NULL), prfd(-1), pwfd(-1) - , rv(false) , name_ (xstrdup(aName)) -{} - -/* yes. we have *real* remote ownership issues with prog and args */ -IPC::IPC (IPC const &old):childFD(old.childFD), mySpawn(old.mySpawn->clone()), - prog (old.prog), args (old.args), - prfd(old.prfd), pwfd (old.pwfd) - , rv(old.rv), name_ (xstrdup(old.name_)) -{} - -bool -IPC::openedInitialFDs() const -{ - if (childFD.rfd < 0) { - debug(54, 0) ("ipcCreate: Failed to create child FD.\n"); - return false; - } - - if (pwfd < 0) { - debug(54, 0) ("ipcCreate: Failed to create server FD.\n"); - return false; - } - - return true; -} - -#ifdef _SQUID_MSWIN_ -static int -ipcSend(int cwfd, const char *buf, int len) -{ - int result = send(cwfd, (const void *) buf, len, 0); - - if (result < 0) { - debug(50, 0) ("sendto FD %d: %s\n", cwfd, xstrerror()); - debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n"); - } - - return result; -} - -struct SpawnResult -{ - SpawnResult() : hProcess (NULL), pid (-1), error (0){} - - HANDLE hProcess; - pid_t pid; - int error; -}; - -static -SpawnResult -ipc_spawn(const char *prog, char **args) -{ - char buf1[8192]; - STARTUPINFO si; - PROCESS_INFORMATION pi; - - memset(&si, 0, sizeof(STARTUPINFO)); - si.cb = sizeof(STARTUPINFO); - si.hStdInput = (HANDLE) _get_osfhandle(0); - si.hStdOutput = (HANDLE) _get_osfhandle(1); - si.hStdError = (HANDLE) _get_osfhandle(2); - si.dwFlags = STARTF_USESTDHANDLES; - - /* Make sure all other valid handles are not inerithable */ - - for (int x = 3; x < SQUID_MAXFD; x++) { - fde *F = &fd_table[x]; - - if (F->win32.handle == 0) - continue; - - SetHandleInformation((HANDLE) F->win32.handle, HANDLE_FLAG_INHERIT, 0); - } - - *buf1 = '\0'; - strcpy(buf1 + 4096, prog); - char *str = strtok(buf1 + 4096, w_space); - - do { - strcat(buf1, str); - strcat(buf1, " "); - } while ((str = strtok(NULL, w_space))); - - int loopIndex = 1; - - while (args[loopIndex]) { - strcat(buf1, args[loopIndex++]); - strcat(buf1, " "); - } - - SpawnResult result; - - if (CreateProcess(buf1 + 4096, buf1, NULL, NULL, TRUE, CREATE_NO_WINDOW, - NULL, NULL, &si, &pi)) { - result.pid = pi.dwProcessId; - result.hProcess = pi.hProcess; - } else { - WIN32_maperror(GetLastError()); - result.error = errno; - } - - return result; -} - -unsigned int -ipc_params::ThreadReflector(void *voidParam) -{ - - struct ipc_params *params = static_cast(voidParam); - unsigned int result = params->threadLoop(); - delete params; - return result; -} - -#endif - -#ifdef _SQUID_MSWIN_ - -WindowsSpawn::WindowsSpawn(): newThread (NULL), data(NULL), - pid(-1), error (0), childRV (0), threadID (0), threadHandle(NULL) -{} - -WindowsSpawn::WindowsSpawn(WindowsSpawn const &old) : Spawn (old), newThread (old.newThread), - data (old.data), pid (old.pid), error (old.error), childRV (old.childRV), threadID (old.threadID) -{ - if (old.threadHandle) - DuplicateHandle (GetCurrentProcess(), old.threadHandle,GetCurrentProcess(), &threadHandle, 0,FALSE,DUPLICATE_SAME_ACCESS); -} - -WindowsSpawn::~WindowsSpawn() -{ - if (threadHandle != NULL) - CloseHandle(threadHandle); - - threadHandle = NULL; -} - -unsigned int __stdcall -WindowsSpawn::ThreadReflector (void *me_) -{ - WindowsSpawn *me = static_cast(me_); - assert (me->newThread != NULL); - me->childRV = me->newThread (me->data); - return me->childRV; -} - -Spawn * -WindowsSpawn::clone() const -{ - WindowsSpawn *result = new WindowsSpawn (*this); - return result; -} - -bool -WindowsSpawn::success() const -{ - return threadID != 0; -} - -void * -WindowsSpawn::getHandle() const -{ - return threadHandle; -} - -pid_t -WindowsSpawn::getPid() const -{ - assert (0); - return pid; -} +static char hello_buf[HELLO_BUF_SZ]; -void -WindowsSpawn::splitExecution(Spawn::Child *_newThread, void *_data) +static int +ipcCloseAllFD(int prfd, int pwfd, int crfd, int cwfd) { - newThread = _newThread; - data = _data; - HANDLE beginRv = - (HANDLE) _beginthreadex(NULL, 0, ThreadReflector, this, 0, &threadID); - - if (!beginRv) { - debug(50, 1) ("ipcCreate: _beginthreadex: %s\n", xstrerror()); - } else { - assert (threadID != 0); - /* undocumented! */ - threadHandle = beginRv; - debug(50, 1) ("WindowsSpawn::splitExecution: Handle: 0x%x, ThreadID: %d\n", (unsigned) threadHandle,threadID); - } -} + if (prfd >= 0) + comm_close(prfd); -#else -UnixSpawn::UnixSpawn() :newThread (NULL), data(NULL), - pid(-1) -{} + if (prfd != pwfd) + if (pwfd >= 0) + comm_close(pwfd); -UnixSpawn::UnixSpawn(UnixSpawn const &old) -{} + if (crfd >= 0) + comm_close(crfd); -Spawn * -UnixSpawn::clone() const -{ - UnixSpawn *result = new UnixSpawn (*this); - return result; -} + if (crfd != cwfd) + if (cwfd >= 0) + comm_close(cwfd); -bool -UnixSpawn::success() const -{ - return pid > -1; + return -1; } -void * -UnixSpawn::getHandle() const +static void +PutEnvironment() { - assert (0); - return NULL; +#if HAVE_PUTENV + char *env_str; + int tmp_s; + env_str = (char *)xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1); + snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions); + putenv(env_str); +#endif } -pid_t -UnixSpawn::getPid() const +int +ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd) { - return pid; -} + pid_t pid; -void -UnixSpawn::splitExecution(Spawn::Child *_newThread, void *_data) -{ - newThread = _newThread; - data = _data; + struct sockaddr_in ChS; - if ((pid = fork()) < 0) { - debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror()); - } else if (pid > 0) { - /* parent */ - return; - } else { - /* Still checked outside here */ - child(); - } -} + struct sockaddr_in PaS; + int crfd = -1; + int prfd = -1; + int cwfd = -1; + int pwfd = -1; + int fd; + int t1, t2, t3; + socklen_t len; + int x; -void -UnixSpawn::child() -{ - /*exit(*/newThread(data)/*)*/; -} +#if USE_POLL && defined(_SQUID_OSF_) + assert(type != IPC_FIFO); #endif -unsigned int -IPC::ForkChild(void *data) -{ - IPC *result = static_cast(data); - assert (result); -#ifndef _SQUID_MSWIN_ - /* child */ - no_suid(); /* give up extra priviliges */ - /* close shared socket with parent */ - comm_close(result->prfd); - - if (result->pwfd != result->prfd) - close(result->pwfd); + if (rfd) + *rfd = -1; - result->pwfd = result->prfd = -1; - -#else -#endif - - /* Until we are entire in this routine */ - return 0; -} + if (wfd) + *wfd = -1; + + if (type == IPC_TCP_SOCKET) { + crfd = cwfd = comm_open(SOCK_STREAM, + 0, + local_addr, + 0, + COMM_NOCLOEXEC, + name); + prfd = pwfd = comm_open(SOCK_STREAM, + 0, /* protocol */ + local_addr, + 0, /* port */ + 0, /* blocking */ + name); + } else if (type == IPC_UDP_SOCKET) { + crfd = cwfd = comm_open(SOCK_DGRAM, + 0, + local_addr, + 0, + COMM_NOCLOEXEC, + name); + prfd = pwfd = comm_open(SOCK_DGRAM, + 0, + local_addr, + 0, + 0, + name); + } else if (type == IPC_FIFO) { + int p2c[2]; + int c2p[2]; + + if (pipe(p2c) < 0) { + debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror()); + return -1; + } + + if (pipe(c2p) < 0) { + debug(50, 0) ("ipcCreate: pipe: %s\n", xstrerror()); + return -1; + } + + fdc_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read"); + fdc_open(cwfd = p2c[1], FD_PIPE, "IPC FIFO Child Write"); + fdc_open(crfd = c2p[0], FD_PIPE, "IPC FIFO Child Read"); + fdc_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write"); +#if HAVE_SOCKETPAIR && defined(AF_UNIX) -IPC * -IPC::Create (int type, const char *prog, const char *const args[], const char *name) -{ - IPC *result = NULL; - /* get our candidate object */ - assert (result = Factory (type, name)); -#ifndef _SQUID_MSWIN_ + } else if (type == IPC_UNIX_STREAM) { + int fds[2]; + int buflen = 32768; + + if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) < 0) { + debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror()); + return -1; + } + + setsockopt(fds[0], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen)); + setsockopt(fds[0], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen)); + setsockopt(fds[1], SOL_SOCKET, SO_SNDBUF, (void *) &buflen, sizeof(buflen)); + setsockopt(fds[1], SOL_SOCKET, SO_RCVBUF, (void *) &buflen, sizeof(buflen)); + fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX STREAM Parent"); + fdc_open(crfd = cwfd = fds[1], FD_PIPE, "IPC UNIX STREAM Parent"); + } else if (type == IPC_UNIX_DGRAM) { + int fds[2]; + + if (socketpair(AF_UNIX, SOCK_DGRAM, 0, fds) < 0) { + debug(50, 0) ("ipcCreate: socketpair: %s\n", xstrerror()); + return -1; + } - int tempFD; + fdc_open(prfd = pwfd = fds[0], FD_PIPE, "IPC UNIX DGRAM Parent"); + fdc_open(crfd = cwfd = fds[1], FD_PIPE, "IPC UNIX DGRAM Parent"); #endif - int x; - - debug(54, 3) ("ipcCreate: prfd FD %d\n", result->prfd); - debug(54, 3) ("ipcCreate: pwfd FD %d\n", result->pwfd); - debug(54, 3) ("ipcCreate: crfd FD %d\n", result->childFD.rfd); - debug(54, 3) ("ipcCreate: cwfd FD %d\n", result->childFD.wfd); - - if (!result->openedInitialFDs()) { - result->cleanUp(); - return result; + } else { + assert(IPC_NONE); } - result->prepFDsForSpawn(); + debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd); + debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd); + debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd); + debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd); - if (!result->preppedFDsForSpawn()) { - result->cleanUp(); - return result; + if (crfd < 0) { + debug(54, 0) ("ipcCreate: Failed to create child FD.\n"); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } - /* flush or else we get dup data if unbuffered_logs is set */ - logsFlush(); - - result->mySpawn = Spawn::GetSpawn(); - - result->prog = prog; - - result->args = const_cast(args); - -#ifdef _SQUID_MSWIN_ + if (pwfd < 0) { + debug(54, 0) ("ipcCreate: Failed to create server FD.\n"); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } - ipc_params *params = new ipc_params (type); + if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { + len = sizeof(PaS); + memset(&PaS, '\0', len); - /* Note to self: we must always clone result, even if - we eliminate the ipc_params class, because using a single instance - might overlap on variable usage. Until the code is fully - reorganised, cloning is safer. - Later on we might want to make threadsafe IPC classes .. - */ - params->myIPC = result->clone(); + if (getsockname(pwfd, (struct sockaddr *) &PaS, &len) < 0) { + debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } - params->prog = prog; + debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", + pwfd, inet_ntoa(PaS.sin_addr), ntohs(PaS.sin_port)); + len = sizeof(ChS); + memset(&ChS, '\0', len); - params->args = (char **) args; + if (getsockname(crfd, (struct sockaddr *) &ChS, &len) < 0) { + debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } - result->mySpawn->splitExecution ((Spawn::Child *)ipc_params::ThreadReflector, params); + debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", + crfd, inet_ntoa(ChS.sin_addr), ntohs(ChS.sin_port)); + } -#else + if (type == IPC_TCP_SOCKET) { + if (listen(crfd, 1) < 0) { + debug(50, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror()); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } - result->mySpawn->splitExecution (ForkChild, result); + debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd); + } -#endif + /* flush or else we get dup data if unbuffered_logs is set */ + logsFlush(); - if (!result->mySpawn->success()) { - result->cleanUp(); - return result; + if ((pid = fork()) < 0) { + debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror()); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } -#ifndef _SQUID_MSWIN_ - if (result->mySpawn->getPid() > 0) { /* parent */ + if (pid > 0) { /* parent */ /* close shared socket with child */ - result->childFD.close(); + comm_close(crfd); - if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { -#else - { - { -#endif + if (cwfd != crfd) + comm_close(cwfd); + + cwfd = crfd = -1; - if (comm_connect_addr(result->pwfd, &result->CS()) == COMM_ERROR) - { - result->cleanUp(); - return result; - } + if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { + if (comm_connect_addr(pwfd, &ChS) == COMM_ERROR) + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } - memset(hello_buf, '\0', HELLO_BUF_SZ); -#ifdef _SQUID_MSWIN_ - x = recv(result->prfd, (void *) hello_buf, HELLO_BUF_SZ - 1, 0); -#else + memset(hello_buf, '\0', HELLO_BUF_SZ); if (type == IPC_UDP_SOCKET) - x = comm_udp_recv(result->prfd, hello_buf, HELLO_BUF_SZ - 1, 0); + x = comm_udp_recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0); else - x = read(result->prfd, hello_buf, HELLO_BUF_SZ - 1); - -#endif + x = read(prfd, hello_buf, HELLO_BUF_SZ - 1); - if (x < 0) - { + if (x < 0) { debug(50, 0) ("ipcCreate: PARENT: hello read test failed\n"); debug(50, 0) ("--> read: %s\n", xstrerror()); - result->cleanUp(); - return result; - } else if (strcmp(hello_buf, hello_string)) - { + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } else if (strcmp(hello_buf, hello_string)) { debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n"); debug(54, 0) ("--> read returned %d\n", x); debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); - result->cleanUp(); - return result; - } - -#ifdef _SQUID_MSWIN_ - x = send(result->pwfd, (const void *) ok_string, strlen(ok_string), 0); - - if (x < 0) - { - debug(50, 0) ("ipcCreate: PARENT: OK write test failed\n"); - debug(50, 0) ("--> read: %s\n", xstrerror()); - result->cleanUp(); - return result; - } - - memset(hello_buf, '\0', HELLO_BUF_SZ); - x = recv(result->prfd, (void *) hello_buf, HELLO_BUF_SZ - 1, 0); - - if (x < 0) - { - debug(50, 0) ("ipcCreate: PARENT: OK read test failed\n"); - debug(50, 0) ("--> read: %s\n", xstrerror()); - result->cleanUp(); - return result; - } else if (!strcmp(hello_buf, err_string)) - { - debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n"); - debug(54, 0) ("--> read returned %d\n", x); - debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); - result->cleanUp(); - return result; + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } - hello_buf[x] = '\0'; - pid_t pid = atol(hello_buf); - HANDLE HProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid); - -#endif - - commSetTimeout(result->prfd, -1, NULL, NULL); - commSetNonBlocking(result->prfd); - commSetNonBlocking(result->pwfd); - fd_table[result->prfd].flags.ipc = 1; - fd_table[result->pwfd].flags.ipc = 1; -#ifdef _SQUID_MSWIN_ - - fd_table[result->childFD.rfd].flags.ipc = 1; - fd_table[result->childFD.wfd].flags.ipc = 1; - - if (Config.sleep_after_fork) - { - /* XXX emulation of usleep() */ - DWORD sl; - sl = Config.sleep_after_fork / 1000; - - if (sl == 0) - sl = 1; + commSetTimeout(prfd, -1, NULL, NULL); + commSetNonBlocking(prfd); + commSetNonBlocking(pwfd); - Sleep(sl); - } + if (rfd) + *rfd = prfd; - DWORD ecode = 0; + if (wfd) + *wfd = pwfd; - if (GetExitCodeThread(result->mySpawn->getHandle(), &ecode) && ecode == STILL_ACTIVE) - { - result->result (IPCResult(true, pid, result->prfd, result->pwfd, HProcess)); - debugs(50, 1, "IPC::Create: Program: " << prog << ", PID: " << ", Handle: 0x" << HProcess); - - return result; - } else - { - result->cleanUp(); - return result; - } + fd_table[prfd].flags.ipc = 1; -#else + fd_table[pwfd].flags.ipc = 1; - if (Config.sleep_after_fork) - { + if (Config.sleep_after_fork) { /* XXX emulation of usleep() */ struct timeval sl; @@ -1436,210 +288,79 @@ select(0, NULL, NULL, NULL, &sl); } - result->result (IPCResult (true, result->mySpawn->getPid(), result->prfd, result->pwfd)); - return result; -#endif - + return pid; } -#ifdef _SQUID_MSWIN_ -} - -unsigned int -ipc_params::threadLoop() { - int t1, t2, t3; - - struct thread_params thread_params; - int tempFD = -1; - char *str; - int tmp_s; - - struct sockaddr_in CS_ipc, PS_ipc; - - strcpy(buf1, prog); - niceprog = strtok(buf1, w_space); - - if ((str = strrchr(niceprog, '/'))) - niceprog = ++str; - - if ((str = strrchr(niceprog, '\\'))) - niceprog = ++str; - - niceprog = xstrdup(niceprog); - - assert (myIPC); - IPC *result = myIPC; - - /* ForkChild is called directly from non windows routines */ - IPC::ForkChild (myIPC); - -#endif - - result->childFDConnect(); - - if (!result->childFDConnected()) { -#ifdef _SQUID_MSWIN_ - freeResources(); - return 1; -#else - - result->cleanUp(); - _exit (1); -#endif - - } + /* child */ + no_suid(); /* give up extra priviliges */ - tempFD = result->childFD.rfd; + /* close shared socket with parent */ + close(prfd); - /* XXX: candidate for extract method */ - { - int sendresult = result->childWrite(hello_string, strlen(hello_string) + 1); + if (pwfd != prfd) + close(pwfd); - if (sendresult < 0) - { - debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n"); -#ifdef _SQUID_MSWIN_ + pwfd = prfd = -1; - freeResources(); - return 1; -#else + if (type == IPC_TCP_SOCKET) { + debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd); - result->cleanUp(); + if ((fd = accept(crfd, NULL, NULL)) < 0) { + debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror()); _exit(1); -#endif - } - } - PutEnvironment(); -#ifndef _SQUID_MSWIN_ - - result->doExec(); - return 0; -#else - - memset(buf1, '\0', sizeof(buf1)); - int recvresult = recv(myIPC->childFD.rfd, (void *) buf1, 8191, 0); - - if (recvresult < 0) { - debug(50, 0) ("ipcCreate: CHILD: OK read test failed\n"); - debug(50, 0) ("--> read: %s\n", xstrerror()); - freeResources(); - return 1; - } else if (strcmp(buf1, ok_string)) { - debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n"); - debug(54, 0) ("--> read returned %d\n", recvresult); - debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); - freeResources(); - return 1; - } - - /* create FDs for child */ - - if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) { - debug(50, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror()); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) { - debug(50, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror()); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; + debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd); + close(crfd); + cwfd = crfd = fd; + } else if (type == IPC_UDP_SOCKET) { + if (comm_connect_addr(crfd, &PaS) == COMM_ERROR) + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); } - /* assign file descriptors to child process */ if (type == IPC_UDP_SOCKET) { - snprintf(buf1, 8192, "%s(%ld) <-> ipc CHILD socket", niceprog, -1L); - crfd_ipc = cwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1); - - if (crfd_ipc < 0) { - debug(54, - 0) ("ipcCreate: CHILD: Failed to create child FD for %s.\n", - niceprog); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - snprintf(buf1, 8192, "%s(%ld) <-> ipc PARENT socket", niceprog, -1L); - prfd_ipc = pwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1); - - if (pwfd_ipc < 0) { - debug(54, - 0) ("ipcCreate: CHILD: Failed to create server FD for %s.\n", - niceprog); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - tmp_s = sizeof(PS_ipc); - memset(&PS_ipc, '\0', tmp_s); - - if (getsockname(pwfd_ipc, (struct sockaddr *) &PS_ipc, &tmp_s) < 0) { - debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", - pwfd_ipc, inet_ntoa(PS_ipc.sin_addr), ntohs(PS_ipc.sin_port)); - tmp_s = sizeof(CS_ipc); - memset(&CS_ipc, '\0', tmp_s); - - if (getsockname(crfd_ipc, (struct sockaddr *) &CS_ipc, &tmp_s) < 0) { - debug(50, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", - crfd_ipc, inet_ntoa(CS_ipc.sin_addr), ntohs(CS_ipc.sin_port)); + x = comm_udp_send(cwfd, hello_string, strlen(hello_string) + 1, 0); - if (comm_connect_addr(pwfd_ipc, &CS_ipc) == COMM_ERROR) { - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; + if (x < 0) { + debug(50, 0) ("sendto FD %d: %s\n", cwfd, xstrerror()); + debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n"); + _exit(1); } - - tempFD = myIPC->childFD.rfd; - - if (comm_connect_addr(crfd_ipc, &PS_ipc) == COMM_ERROR) { - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; + } else { + if (write(cwfd, hello_string, strlen(hello_string) + 1) < 0) { + debug(50, 0) ("write FD %d: %s\n", cwfd, xstrerror()); + debug(50, 0) ("ipcCreate: CHILD: hello write test failed\n"); + _exit(1); } - } /* IPC_UDP_SOCKET */ - - assert (tempFD == myIPC->childFD.rfd); - - t1 = dup(0); - - t2 = dup(1); + } - t3 = dup(2); + PutEnvironment(); + /* + * This double-dup stuff avoids problems when one of + * crfd, cwfd, or debug_log are in the rage 0-2. + */ - dup2(c2p[0], 0); + do { + /* First make sure 0-2 is occupied by something. Gets cleaned up later */ + x = dup(crfd); + assert(x > -1); + } while (x < 3 && x > -1); - dup2(p2c[1], 1); + close(x); - dup2(fileno(debug_log), 2); + t1 = dup(crfd); - close(c2p[0]); + t2 = dup(cwfd); - close(p2c[1]); + t3 = dup(fileno(debug_log)); - commUnsetNonBlocking(tempFD); + assert(t1 > 2 && t2 > 2 && t3 > 2); - SpawnResult spawnResult = ipc_spawn (prog, args); + close(crfd); - pid = spawnResult.pid; + close(cwfd); - hProcess = spawnResult.hProcess; + close(fileno(debug_log)); dup2(t1, 0); @@ -1653,315 +374,22 @@ close(t3); - if (pid == -1) { - errno = spawnResult.error; - debug(50, 0) ("ipcCreate: CHILD: %s: %s\n", prog, xstrerror()); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - /* Ok, the child has started */ - if (type == IPC_UDP_SOCKET) { - WSAPROTOCOL_INFO wpi; - - memset(&wpi, 0, sizeof(wpi)); - - if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc, pid, &wpi)) { - debug(50, 0) ("ipcCreate: CHILD: WSADuplicateSocket: %s\n", - xstrerror()); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - int writeresult = write(c2p[1], (const char *) &wpi, sizeof(wpi)); - - if (writeresult < 0 || static_cast (writeresult) < sizeof(wpi)) { - debug(50, 0) - ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1], - xstrerror()); - debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", - niceprog); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - int readresult = read(p2c[0], buf1, 8192); - - if (readresult < 0) { - debug(50, 0) - ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0], - xstrerror()); - debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", - niceprog); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } else if (strncmp(buf1, ok_string, strlen(ok_string))) { - debug(54, 0) - ("ipcCreate: CHILD: %s: socket exchange failed\n", - niceprog); - debug(54, 0) ("--> read returned %d\n", readresult); - buf1[readresult] = '\0'; - debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1)); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - int write2result = write(c2p[1], (const char *) &PS_ipc, sizeof(PS_ipc)); - - if (write2result < 0 || static_cast(write2result) < sizeof(PS_ipc)) { - debug(50, 0) - ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1], - xstrerror()); - debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", - niceprog); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - int read2result = read(p2c[0], buf1, 8192); - - if (read2result < 0) { - debug(50, 0) - ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0], - xstrerror()); - debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", - niceprog); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } else if (strncmp(buf1, ok_string, strlen(ok_string))) { - debug(54, 0) - ("ipcCreate: CHILD: %s: socket exchange failed\n", - niceprog); - debug(54, 0) ("--> read returned %d\n", read2result); - buf1[read2result] = '\0'; - debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1)); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - /* We should error check this send */ - send(pwfd_ipc, (const void *) ok_string, strlen(ok_string), 0); - int recvrv = recv(prfd_ipc, (void *) (buf1 + 200), 8191 - 200, 0); - assert((size_t) recvrv == strlen(ok_string) - && !strncmp(ok_string, buf1 + 200, strlen(ok_string))); - } /* IPC_UDP_SOCKET */ - - snprintf(buf1, 8191, "%s(%ld) CHILD socket", niceprog, (long int)pid); - - fd_note(tempFD, buf1); - - if (prfd_ipc != -1) { - snprintf(buf1, 8191, "%s(%ld) <-> ipc CHILD socket", niceprog, (long int)pid); - fd_note(crfd_ipc, buf1); - snprintf(buf1, 8191, "%s(%ld) <-> ipc PARENT socket", niceprog, (long int)pid); - fd_note(prfd_ipc, buf1); - } /* else { // IPC_TCP_SOCKET - - * commSetNoLinger(fd); - * } - */ - thread_params.prog = niceprog; - - thread_params.send_fd = myIPC->childFD.wfd; - - thread_params.pid = pid; - - if ((thread_params.type = type) == IPC_TCP_SOCKET) - thread_params.rfd = p2c[0]; - else - thread_params.rfd = prfd_ipc; - - thread = - (HANDLE) _beginthreadex(NULL, 0, ipc_thread_2, &thread_params, 0, NULL); - - if (!thread) { - debug(50, 0) ("ipcCreate: CHILD: _beginthreadex: %s\n", xstrerror()); - ipcSend(myIPC->childFD.wfd, err_string, strlen(err_string)); - freeResources(); - return 1; - } - - snprintf(buf1, 8191, "%ld\n", (long int)pid); - - if (-1 == ipcSend(myIPC->childFD.wfd, buf1, strlen(buf1))) { - freeResources(); - return 1; - } - - debug(54, 2) ("ipc(%s,%ld): started successfully\n", niceprog, (long int)pid); - parentToChildLoop(); - - normalExit(); - freeResources(); - return 0; -} - -void -ipc_params::normalExit() { - debug(54, 2) ("ipc(%s,%d): normal exit\n", niceprog, pid); -} - -void -ipc_params::freeResources() { - if (c2p[1] != -1) - close(c2p[1]); - - if (fd_table[myIPC->childFD.rfd].flags.open) - myIPC->childFD.close(); - - if (prfd_ipc != -1) { - send(crfd_ipc, (const void *) shutdown_string, strlen(shutdown_string), 0); - shutdown(crfd_ipc, SD_BOTH); - shutdown(prfd_ipc, SD_BOTH); - } - - ipcCloseAllFD(prfd_ipc, pwfd_ipc); - myIPC->childFD.close(); - - if (hProcess && WAIT_OBJECT_0 != - WaitForSingleObject(hProcess, type == IPC_UDP_SOCKET ? 12000 : 5000)) { - - getCurrentTime(); - debug(54, 0) ("ipc(%s,%d): WARNING: %s didn't exit in %d seconds.\n", - niceprog, pid, niceprog, type == IPC_UDP_SOCKET ? 12 : 5); - } - - if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) { - getCurrentTime(); - debug(54, 0) - ("ipc(%s,%d): WARNING: ipc_thread_2 didn't exit in 3 seconds.\n", - niceprog, pid); - } - - getCurrentTime(); - safe_free(niceprog); -#if HAVE_PUTENV - - safe_free(env_str); -#endif - - if (thread) - CloseHandle(thread); - - if (hProcess) - CloseHandle(hProcess); - - if (p2c[0] != -1) - close(p2c[0]); - -#endif -} - -#ifdef _SQUID_MSWIN_ -void -ipc_params::parentToChildLoop() { - /* cycle */ - - for (;;) { - int recvrv = recv(myIPC->childFD.rfd, (void *) buf1, 8192, 0); - - if (recvrv <= 0) { - debug(54, 3) ("ipc(%s,%d): %d bytes received from parent. Exiting...\n", - niceprog, pid, recvrv); - return; - } - - buf1[recvrv] = '\0'; - - if (type == IPC_UDP_SOCKET && !strcmp(buf1, shutdown_string)) { - debug(54, 3) - ("ipc(%s,%d): request for shutdown received from parent. Exiting...\n", - niceprog, pid); - // TerminateProcess(hProcess, 0); - return; - } - - debug(54, 5) ("ipc(%s,%d): received from parent: %s\n", niceprog, pid, - rfc1738_escape_unescaped(buf1)); - int writerv; - - if (type == IPC_TCP_SOCKET) - writerv = write(c2p[1], buf1, recvrv); - else - writerv = send(pwfd_ipc, (const void *) buf1, recvrv, 0); + /* Make sure all other filedescriptors are closed */ + for (x = 3; x < SQUID_MAXFD; x++) + close(x); - if (writerv <= 0) { - debug(54, 3) ("ipc(%s,%d): %d bytes written to %s. Exiting...\n", - niceprog, pid, writerv, niceprog); - return; - } + if (opt_no_daemon) { + squid_signal(SIGINT, SIG_IGN, SA_RESETHAND); + squid_signal(SIGHUP, SIG_IGN, SA_RESETHAND); } -} - -#endif - -void -IPCInstance::childToParentLoop() { - char buf2[8192]; - - for (;;) { - int x; - - if (type == IPC_TCP_SOCKET) - x = read(prfd, buf2, 8192); - else - x = recv(prfd, (void *) buf2, 8192, 0); - if ((x <= 0 && type == IPC_TCP_SOCKET) || - (x < 0 && type == IPC_UDP_SOCKET)) { - debug(54, 3) ("ipc(%s,%d): %d bytes read from %s. Exiting...\n", - prog, pid, x, prog); - break; - } - - buf2[x] = '\0'; - - if (type == IPC_UDP_SOCKET && !strcmp(buf2, ShutdownMessage)) { - debug(54, 3) ("ipc(%s,%d): request for shutdown received. Exiting...\n", - prog, pid); - break; - } - - if (x >= 2) { - if ((buf2[x-1] == '\n') && (buf2[x-2] == '\r')) { - buf2[x-2] = '\n'; - buf2[x-1] = '\0'; - x--; - } - } - - debug(54, 5) ("ipc(%s,%d): received from child : %s\n", prog, pid, - rfc1738_escape_unescaped(buf2)); - x = send(send_fd, (const void *) buf2, x, 0); - - if ((x <= 0 && type == IPC_TCP_SOCKET) || - (x < 0 && type == IPC_UDP_SOCKET)) { - debug(54, 3) ("ipc(%s,%d): %d bytes sent to parent. Exiting...\n", - prog, pid, x); - break; - } - } -} + execvp(prog, (char *const *) args); -#ifdef _SQUID_MSWIN_ -static unsigned int __stdcall -ipc_thread_2(void *voidParam) { + debug_log = fdopen(2, "a+"); - struct thread_params *params = static_cast(voidParam); - IPCInstance *newInstance = new IPCInstance(params->type, params->pid, params->prog, params->rfd, params->send_fd); + debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror()); - newInstance->childToParentLoop(); + _exit(1); - delete newInstance; return 0; } - -#endif --- squid3/src/ipc.h Wed Feb 14 13:37:49 2007 +++ /dev/null Wed Feb 14 13:37:19 2007 @@ -1,88 +0,0 @@ - -/* - * $Id: ipc.h,v 1.1.18.1 2003/02/25 02:49:12 hno Exp $ - * - * - * SQUID Web Proxy Cache http://www.squid-cache.org/ - * ---------------------------------------------------------- - * - * Squid is the result of efforts by numerous individuals from - * the Internet community; see the CONTRIBUTORS file for full - * details. Many organizations have provided support for Squid's - * development; see the SPONSORS file for full details. Squid is - * Copyrighted (C) 2001 by the Regents of the University of - * California; see the COPYRIGHT file for full details. Squid - * incorporates software developed and/or copyrighted by other - * sources; see the CREDITS file for full details. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. - * - */ - -#ifndef SQUID_IPC_H -#define SQUID_IPC_H - - -#define IPC_NONE 0 -#define IPC_TCP_SOCKET 1 -#define IPC_UDP_SOCKET 2 - -#ifndef _SQUID_MSWIN_ - -#if !(USE_POLL && defined(_SQUID_OSF_)) - -#define IPC_FIFO 3 - -#endif - -#define IPC_UNIX_STREAM 4 -#define IPC_UNIX_DGRAM 5 -#endif - -#if HAVE_SOCKETPAIR && defined (AF_UNIX) -#define IPC_STREAM IPC_UNIX_STREAM -#define IPC_DGRAM IPC_UNIX_DGRAM -#else -#define IPC_STREAM IPC_TCP_SOCKET -#define IPC_DGRAM IPC_UDP_SOCKET -#endif - -struct IPCResult { - IPCResult (int causelinkfailure); - IPCResult (bool aBool, pid_t aPid=-1, int _rfd=-1, int _wfd = -1 -#ifdef _SQUID_MSWIN_ - ,HANDLE aHandle=NULL -#endif - ) : success(aBool), pid (aPid), rfd (_rfd), wfd (_wfd) -#ifdef _SQUID_MSWIN_ - ,hIpc(aHandle) -#endif - {} - bool success; - pid_t pid; - int rfd; - int wfd; -#ifdef _SQUID_MSWIN_ - HANDLE hIpc; -#endif -}; - -IPCResult ipcCreate(int type, - const char *prog, - const char *const args[], - const char *name -); - -#endif /* SQUID_IPC_H */ --- /dev/null Wed Feb 14 13:37:19 2007 +++ squid3/src/ipc_win32.cc Wed Feb 14 13:37:49 2007 @@ -0,0 +1,863 @@ + +/* + * $Id: ipc_win32.cc,v 1.1.2.1 2006/09/03 16:51:26 serassio Exp $ + * + * DEBUG: section 54 Interprocess Communication + * AUTHOR: Duane Wessels + * + * SQUID Web Proxy Cache http://www.squid-cache.org/ + * ---------------------------------------------------------- + * + * Squid is the result of efforts by numerous individuals from + * the Internet community; see the CONTRIBUTORS file for full + * details. Many organizations have provided support for Squid's + * development; see the SPONSORS file for full details. Squid is + * Copyrighted (C) 2001 by the Regents of the University of + * California; see the COPYRIGHT file for full details. Squid + * incorporates software developed and/or copyrighted by other + * sources; see the CREDITS file for full details. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA. + * + */ + +#include "squid.h" +#include "comm.h" +#include "fde.h" +#include "SquidTime.h" + +#ifndef _MSWSOCK_ +#include +#endif +#include + +struct ipc_params +{ + int type; + int crfd; + int cwfd; + + struct sockaddr_in PS; + const char *prog; + char **args; +}; + +struct thread_params +{ + int type; + int rfd; + int send_fd; + const char *prog; + pid_t pid; +}; + +static unsigned int __stdcall ipc_thread_1(void *params); +static unsigned int __stdcall ipc_thread_2(void *params); + +static const char *ok_string = "OK\n"; +static const char *err_string = "ERR\n"; +static const char *shutdown_string = "$shutdown\n"; + +static const char *hello_string = "hi there\n"; +#define HELLO_BUF_SZ 32 +static char hello_buf[HELLO_BUF_SZ]; + +static int +ipcCloseAllFD(int prfd, int pwfd, int crfd, int cwfd) +{ + if (prfd >= 0) + comm_close(prfd); + + if (prfd != pwfd) + if (pwfd >= 0) + comm_close(pwfd); + + if (crfd >= 0) + comm_close(crfd); + + if (crfd != cwfd) + if (cwfd >= 0) + comm_close(cwfd); + + return -1; +} + +static void +PutEnvironment() +{ +#if HAVE_PUTENV + char *env_str; + int tmp_s; + env_str = (char *)xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1); + snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions); + putenv(env_str); +#endif +} + +pid_t +ipcCreate(int type, const char *prog, const char *const args[], const char *name, int *rfd, int *wfd, void **hIpc) +{ + unsigned long thread; + + struct ipc_params params; + int opt; + int optlen = sizeof(opt); + DWORD ecode = 0; + pid_t pid; + + struct sockaddr_in CS; + + struct sockaddr_in PS; + int crfd = -1; + int prfd = -1; + int cwfd = -1; + int pwfd = -1; + socklen_t len; + int x; + + requirePathnameExists(name, prog); + + if (rfd) + *rfd = -1; + + if (wfd) + *wfd = -1; + + if (hIpc) + *hIpc = NULL; + + if (WIN32_OS_version != _WIN_OS_WINNT) { + getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen); + opt = opt & ~(SO_SYNCHRONOUS_NONALERT | SO_SYNCHRONOUS_ALERT); + setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, sizeof(opt)); + } + + if (type == IPC_TCP_SOCKET) { + crfd = cwfd = comm_open(SOCK_STREAM, + IPPROTO_TCP, + local_addr, + 0, + COMM_NOCLOEXEC, + name); + prfd = pwfd = comm_open(SOCK_STREAM, + IPPROTO_TCP, /* protocol */ + local_addr, + 0, /* port */ + 0, /* blocking */ + name); + } else if (type == IPC_UDP_SOCKET) { + crfd = cwfd = comm_open(SOCK_DGRAM, + IPPROTO_UDP, + local_addr, + 0, + COMM_NOCLOEXEC, + name); + prfd = pwfd = comm_open(SOCK_DGRAM, + IPPROTO_UDP, + local_addr, + 0, + 0, + name); + } else if (type == IPC_FIFO) { + debug(54, 0) + ("ipcCreate: %s: use IPC_TCP_SOCKET instead of IP_FIFO on Windows\n", + prog); + assert(0); + } else { + assert(IPC_NONE); + } + + debug(54, 3) ("ipcCreate: prfd FD %d\n", prfd); + debug(54, 3) ("ipcCreate: pwfd FD %d\n", pwfd); + debug(54, 3) ("ipcCreate: crfd FD %d\n", crfd); + debug(54, 3) ("ipcCreate: cwfd FD %d\n", cwfd); + + if (WIN32_OS_version != _WIN_OS_WINNT) { + getsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, &optlen); + opt = opt | SO_SYNCHRONOUS_NONALERT; + setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE, (char *) &opt, optlen); + } + + if (crfd < 0) { + debug(54, 0) ("ipcCreate: Failed to create child FD.\n"); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } + + if (pwfd < 0) { + debug(54, 0) ("ipcCreate: Failed to create server FD.\n"); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } + + if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { + len = sizeof(PS); + memset(&PS, '\0', len); + + if (getsockname(pwfd, (struct sockaddr *) &PS, &len) < 0) { + debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } + + debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", + pwfd, inet_ntoa(PS.sin_addr), ntohs(PS.sin_port)); + len = sizeof(CS); + memset(&CS, '\0', len); + + if (getsockname(crfd, (struct sockaddr *) &CS, &len) < 0) { + debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } + + debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", + crfd, inet_ntoa(CS.sin_addr), ntohs(CS.sin_port)); + } + + if (type == IPC_TCP_SOCKET) { + if (listen(crfd, 1) < 0) { + debug(54, 1) ("ipcCreate: listen FD %d: %s\n", crfd, xstrerror()); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } + + debug(54, 3) ("ipcCreate: FD %d listening...\n", crfd); + } + + /* flush or else we get dup data if unbuffered_logs is set */ + logsFlush(); + + params.type = type; + + params.crfd = crfd; + + params.cwfd = cwfd; + + params.PS = PS; + + params.prog = prog; + + params.args = (char **) args; + + thread = _beginthreadex(NULL, 0, ipc_thread_1, ¶ms, 0, NULL); + + if (thread == 0) { + debug(54, 1) ("ipcCreate: _beginthread: %s\n", xstrerror()); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } + + if (comm_connect_addr(pwfd, &CS) == COMM_ERROR) { + CloseHandle((HANDLE) thread); + return ipcCloseAllFD(prfd, pwfd, -1, -1); + } + + memset(hello_buf, '\0', HELLO_BUF_SZ); + x = recv(prfd, (void *)hello_buf, HELLO_BUF_SZ - 1, 0); + + if (x < 0) { + debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n"); + debug(54, 0) ("--> read: %s\n", xstrerror()); + CloseHandle((HANDLE) thread); + return ipcCloseAllFD(prfd, pwfd, -1, -1); + } else if (strcmp(hello_buf, hello_string)) { + debug(54, 0) ("ipcCreate: PARENT: hello read test failed\n"); + debug(54, 0) ("--> read returned %d\n", x); + debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); + CloseHandle((HANDLE) thread); + return ipcCloseAllFD(prfd, pwfd, -1, -1); + } + + x = send(pwfd, (const void *)ok_string, strlen(ok_string), 0); + + if (x < 0) { + debug(54, 0) ("ipcCreate: PARENT: OK write test failed\n"); + debug(54, 0) ("--> read: %s\n", xstrerror()); + CloseHandle((HANDLE) thread); + return ipcCloseAllFD(prfd, pwfd, -1, -1); + } + + memset(hello_buf, '\0', HELLO_BUF_SZ); + x = recv(prfd, (void *)hello_buf, HELLO_BUF_SZ - 1, 0); + + if (x < 0) { + debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n"); + debug(54, 0) ("--> read: %s\n", xstrerror()); + CloseHandle((HANDLE) thread); + return ipcCloseAllFD(prfd, pwfd, -1, -1); + } else if (!strcmp(hello_buf, err_string)) { + debug(54, 0) ("ipcCreate: PARENT: OK read test failed\n"); + debug(54, 0) ("--> read returned %d\n", x); + debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); + CloseHandle((HANDLE) thread); + return ipcCloseAllFD(prfd, pwfd, -1, -1); + } + + hello_buf[x] = '\0'; + pid = atol(hello_buf); + commSetTimeout(prfd, -1, NULL, NULL); + commSetNonBlocking(prfd); + commSetNonBlocking(pwfd); + commSetCloseOnExec(prfd); + commSetCloseOnExec(pwfd); + + if (rfd) + *rfd = prfd; + + if (wfd) + *wfd = pwfd; + + fd_table[prfd].flags.ipc = 1; + + fd_table[pwfd].flags.ipc = 1; + + fd_table[crfd].flags.ipc = 1; + + fd_table[cwfd].flags.ipc = 1; + + if (Config.sleep_after_fork) { + /* XXX emulation of usleep() */ + DWORD sl; + sl = Config.sleep_after_fork / 1000; + + if (sl == 0) + sl = 1; + + Sleep(sl); + } + + if (GetExitCodeThread((HANDLE) thread, &ecode) && ecode == STILL_ACTIVE) { + if (hIpc) + *hIpc = (HANDLE) thread; + + return pid; + } else { + CloseHandle((HANDLE) thread); + return ipcCloseAllFD(prfd, pwfd, -1, -1); + } +} + +static int +ipcSend(int cwfd, const char *buf, int len) +{ + int x; + + x = send(cwfd, (const void *)buf, len, 0); + + if (x < 0) { + debug(54, 0) ("sendto FD %d: %s\n", cwfd, xstrerror()); + debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n"); + } + + return x; +} + +static unsigned int __stdcall +ipc_thread_1(void *in_params) +{ + int t1, t2, t3, retval = -1; + int p2c[2] = + {-1, -1}; + int c2p[2] = + {-1, -1}; + HANDLE hProcess = NULL, thread = NULL; + pid_t pid = -1; + + struct thread_params thread_params; + ssize_t x; + int tmp_s, fd = -1; + char *str; + STARTUPINFO si; + PROCESS_INFORMATION pi; + long F; + int prfd_ipc = -1, pwfd_ipc = -1, crfd_ipc = -1, cwfd_ipc = -1; + char *prog = NULL, *buf1 = NULL; + + struct sockaddr_in CS_ipc, PS_ipc; + + struct ipc_params *params = (struct ipc_params *) in_params; + int type = params->type; + int crfd = params->crfd; + int cwfd = params->cwfd; + char **args = params->args; + + struct sockaddr_in PS = params->PS; + + + buf1 = (char *)xcalloc(1, 8192); + strcpy(buf1, params->prog); + prog = strtok(buf1, w_space); + + if ((str = strrchr(prog, '/'))) + prog = ++str; + + if ((str = strrchr(prog, '\\'))) + prog = ++str; + + prog = xstrdup(prog); + + if (type == IPC_TCP_SOCKET) { + debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd); + + if ((fd = accept(crfd, NULL, NULL)) < 0) { + debug(54, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror()); + goto cleanup; + } + + debug(54, 3) ("ipcCreate: CHILD accepted new FD %d\n", fd); + comm_close(crfd); + snprintf(buf1, 8191, "%s CHILD socket", prog); + fd_open(fd, FD_SOCKET, buf1); + fd_table[fd].flags.ipc = 1; + cwfd = crfd = fd; + } else if (type == IPC_UDP_SOCKET) { + if (comm_connect_addr(crfd, &PS) == COMM_ERROR) + goto cleanup; + } + + x = send(cwfd, (const void *)hello_string, strlen(hello_string) + 1, 0); + + if (x < 0) { + debug(54, 0) ("sendto FD %d: %s\n", cwfd, xstrerror()); + debug(54, 0) ("ipcCreate: CHILD: hello write test failed\n"); + goto cleanup; + } + + PutEnvironment(); + memset(buf1, '\0', sizeof(buf1)); + x = recv(crfd, (void *)buf1, 8191, 0); + + if (x < 0) { + debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n"); + debug(54, 0) ("--> read: %s\n", xstrerror()); + goto cleanup; + } else if (strcmp(buf1, ok_string)) { + debug(54, 0) ("ipcCreate: CHILD: OK read test failed\n"); + debug(54, 0) ("--> read returned %d\n", x); + debug(54, 0) ("--> got '%s'\n", rfc1738_escape(hello_buf)); + goto cleanup; + } + + /* assign file descriptors to child process */ + if (_pipe(p2c, 1024, _O_BINARY | _O_NOINHERIT) < 0) { + debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror()); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + if (_pipe(c2p, 1024, _O_BINARY | _O_NOINHERIT) < 0) { + debug(54, 0) ("ipcCreate: CHILD: pipe: %s\n", xstrerror()); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + if (type == IPC_UDP_SOCKET) { + snprintf(buf1, 8192, "%s(%ld) <-> ipc CHILD socket", prog, -1L); + crfd_ipc = cwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1); + + if (crfd_ipc < 0) { + debug(54, 0) ("ipcCreate: CHILD: Failed to create child FD for %s.\n", + prog); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + snprintf(buf1, 8192, "%s(%ld) <-> ipc PARENT socket", prog, -1L); + prfd_ipc = pwfd_ipc = comm_open(SOCK_DGRAM, IPPROTO_UDP, local_addr, 0, 0, buf1); + + if (pwfd_ipc < 0) { + debug(54, 0) ("ipcCreate: CHILD: Failed to create server FD for %s.\n", + prog); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + tmp_s = sizeof(PS_ipc); + memset(&PS_ipc, '\0', tmp_s); + + if (getsockname(pwfd_ipc, (struct sockaddr *) &PS_ipc, &tmp_s) < 0) { + debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", + pwfd_ipc, inet_ntoa(PS_ipc.sin_addr), ntohs(PS_ipc.sin_port)); + tmp_s = sizeof(CS_ipc); + memset(&CS_ipc, '\0', tmp_s); + + if (getsockname(crfd_ipc, (struct sockaddr *) &CS_ipc, &tmp_s) < 0) { + debug(54, 0) ("ipcCreate: getsockname: %s\n", xstrerror()); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + debug(54, 3) ("ipcCreate: FD %d sockaddr %s:%d\n", + crfd_ipc, inet_ntoa(CS_ipc.sin_addr), ntohs(CS_ipc.sin_port)); + + if (comm_connect_addr(pwfd_ipc, &CS_ipc) == COMM_ERROR) { + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + fd = crfd; + + if (comm_connect_addr(crfd_ipc, &PS_ipc) == COMM_ERROR) { + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + } /* IPC_UDP_SOCKET */ + + t1 = dup(0); + + t2 = dup(1); + + t3 = dup(2); + + dup2(c2p[0], 0); + + dup2(p2c[1], 1); + + dup2(fileno(debug_log), 2); + + close(c2p[0]); + + close(p2c[1]); + + commUnsetNonBlocking(fd); + + memset(&si, 0, sizeof(STARTUPINFO)); + + si.cb = sizeof(STARTUPINFO); + + si.hStdInput = (HANDLE) _get_osfhandle(0); + + si.hStdOutput = (HANDLE) _get_osfhandle(1); + + si.hStdError = (HANDLE) _get_osfhandle(2); + + si.dwFlags = STARTF_USESTDHANDLES; + + /* Make sure all other valid handles are not inerithable */ + for (x = 3; x < Squid_MaxFD; x++) { + if ((F = _get_osfhandle(x)) == -1) + continue; + + SetHandleInformation((HANDLE) F, HANDLE_FLAG_INHERIT, 0); + } + + *buf1 = '\0'; + strcpy(buf1 + 4096, params->prog); + str = strtok(buf1 + 4096, w_space); + + do { + strcat(buf1, str); + strcat(buf1, " "); + } while ((str = strtok(NULL, w_space))); + + x = 1; + + while (args[x]) { + strcat(buf1, args[x++]); + strcat(buf1, " "); + } + + if (CreateProcess(buf1 + 4096, buf1, NULL, NULL, TRUE, CREATE_NO_WINDOW, + NULL, NULL, &si, &pi)) { + pid = pi.dwProcessId; + hProcess = pi.hProcess; + } else { + pid = -1; + WIN32_maperror(GetLastError()); + x = errno; + } + + dup2(t1, 0); + dup2(t2, 1); + dup2(t3, 2); + close(t1); + close(t2); + close(t3); + + if (pid == -1) { + errno = x; + debug(54, 0) ("ipcCreate: CHILD: %s: %s\n", params->prog, xstrerror()); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + if (type == IPC_UDP_SOCKET) { + WSAPROTOCOL_INFO wpi; + + memset(&wpi, 0, sizeof(wpi)); + + if (SOCKET_ERROR == WSADuplicateSocket(crfd_ipc, pid, &wpi)) { + debug(54, 0) ("ipcCreate: CHILD: WSADuplicateSocket: %s\n", + xstrerror()); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + x = write(c2p[1], (const char *) &wpi, sizeof(wpi)); + + if (x < (ssize_t)sizeof(wpi)) { + debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1], + xstrerror()); + debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", + prog); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + x = read(p2c[0], buf1, 8192); + + if (x < 0) { + debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0], + xstrerror()); + debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", + prog); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } else if (strncmp(buf1, ok_string, strlen(ok_string))) { + debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", + prog); + debug(54, 0) ("--> read returned %d\n", x); + buf1[x] = '\0'; + debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1)); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + x = write(c2p[1], (const char *) &PS_ipc, sizeof(PS_ipc)); + + if (x < (ssize_t)sizeof(PS_ipc)) { + debug(54, 0) ("ipcCreate: CHILD: write FD %d: %s\n", c2p[1], + xstrerror()); + debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", + prog); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + x = read(p2c[0], buf1, 8192); + + if (x < 0) { + debug(54, 0) ("ipcCreate: CHILD: read FD %d: %s\n", p2c[0], + xstrerror()); + debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", + prog); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } else if (strncmp(buf1, ok_string, strlen(ok_string))) { + debug(54, 0) ("ipcCreate: CHILD: %s: socket exchange failed\n", + prog); + debug(54, 0) ("--> read returned %d\n", x); + buf1[x] = '\0'; + debug(54, 0) ("--> got '%s'\n", rfc1738_escape(buf1)); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + x = send(pwfd_ipc, (const void *)ok_string, strlen(ok_string), 0); + x = recv(prfd_ipc, (void *)(buf1 + 200), 8191 - 200, 0); + assert((size_t) x == strlen(ok_string) + && !strncmp(ok_string, buf1 + 200, strlen(ok_string))); + } /* IPC_UDP_SOCKET */ + + snprintf(buf1, 8191, "%s(%ld) CHILD socket", prog, (long int) pid); + + fd_note(fd, buf1); + + if (prfd_ipc != -1) { + snprintf(buf1, 8191, "%s(%ld) <-> ipc CHILD socket", prog, (long int) pid); + fd_note(crfd_ipc, buf1); + snprintf(buf1, 8191, "%s(%ld) <-> ipc PARENT socket", prog, (long int) pid); + fd_note(prfd_ipc, buf1); + } + + /* else { IPC_TCP_SOCKET */ + /* commSetNoLinger(fd); */ + /* } */ + thread_params.prog = prog; + + thread_params.send_fd = cwfd; + + thread_params.pid = pid; + + if ((thread_params.type = type) == IPC_TCP_SOCKET) + thread_params.rfd = p2c[0]; + else + thread_params.rfd = prfd_ipc; + + thread = + (HANDLE) _beginthreadex(NULL, 0, ipc_thread_2, &thread_params, 0, NULL); + + if (!thread) { + debug(54, 0) ("ipcCreate: CHILD: _beginthreadex: %s\n", xstrerror()); + ipcSend(cwfd, err_string, strlen(err_string)); + goto cleanup; + } + + snprintf(buf1, 8191, "%ld\n", (long int) pid); + + if (-1 == ipcSend(cwfd, buf1, strlen(buf1))) + goto cleanup; + + debug(54, 2) ("ipc(%s,%ld): started successfully\n", prog, (long int) pid); + + /* cycle */ + for (;;) { + x = recv(crfd, (void *)buf1, 8192, 0); + + if (x <= 0) { + debug(54, 3) ("ipc(%s,%d): %d bytes received from parent. Exiting...\n", + prog, pid, x); + break; + } + + buf1[x] = '\0'; + + if (type == IPC_UDP_SOCKET && !strcmp(buf1, shutdown_string)) { + debug(54, 3) + ("ipc(%s,%d): request for shutdown received from parent. Exiting...\n", + prog, pid); + TerminateProcess(hProcess, 0); + break; + } + + debug(54, 5) ("ipc(%s,%d): received from parent: %s\n", prog, pid, + rfc1738_escape_unescaped(buf1)); + + if (type == IPC_TCP_SOCKET) + x = write(c2p[1], buf1, x); + else + x = send(pwfd_ipc, (const void *)buf1, x, 0); + + if (x <= 0) { + debug(54, 3) ("ipc(%s,%d): %d bytes written to %s. Exiting...\n", + prog, pid, x, prog); + break; + } + } + + retval = 0; + +cleanup: + + if (c2p[1] != -1) + close(c2p[1]); + + if (fd_table[crfd].flags.open) + ipcCloseAllFD(-1, -1, crfd, cwfd); + + if (prfd_ipc != -1) { + send(crfd_ipc, (const void *)shutdown_string, strlen(shutdown_string), 0); + shutdown(crfd_ipc, SD_BOTH); + shutdown(prfd_ipc, SD_BOTH); + } + + ipcCloseAllFD(prfd_ipc, pwfd_ipc, crfd_ipc, cwfd_ipc); + + if (hProcess && WAIT_OBJECT_0 != + WaitForSingleObject(hProcess, type == IPC_UDP_SOCKET ? 12000 : 5000)) { + + getCurrentTime(); + debug(54, 0) ("ipc(%s,%d): WARNING: %s didn't exit in %d seconds.\n", + prog, pid, prog, type == IPC_UDP_SOCKET ? 12 : 5); + } + + if (thread && WAIT_OBJECT_0 != WaitForSingleObject(thread, 3000)) { + getCurrentTime(); + debug(54, 0) + ("ipc(%s,%d): WARNING: ipc_thread_2 didn't exit in 3 seconds.\n", + prog, pid); + } + + getCurrentTime(); + + if (!retval) + debug(54, 2) ("ipc(%s,%d): normal exit\n", prog, pid); + + if (buf1) + xfree(buf1); + + if (prog) + xfree(prog); + + if (thread) + CloseHandle(thread); + + if (hProcess) + CloseHandle(hProcess); + + if (p2c[0] != -1) + close(p2c[0]); + + return retval; +} + +static unsigned int __stdcall +ipc_thread_2(void *in_params) +{ + int x; + + struct thread_params *params = (struct thread_params *) in_params; + int type = params->type; + int rfd = params->rfd; + int send_fd = params->send_fd; + char *prog = xstrdup(params->prog); + pid_t pid = params->pid; + char *buf2 = (char *)xcalloc(1, 8192); + + for (;;) { + if (type == IPC_TCP_SOCKET) + x = read(rfd, buf2, 8192); + else + x = recv(rfd, (void *)buf2, 8192, 0); + + if ((x <= 0 && type == IPC_TCP_SOCKET) || + (x < 0 && type == IPC_UDP_SOCKET)) { + debug(54, 3) ("ipc(%s,%d): %d bytes read from %s. Exiting...\n", + prog, pid, x, prog); + break; + } + + buf2[x] = '\0'; + + if (type == IPC_UDP_SOCKET && !strcmp(buf2, shutdown_string)) { + debug(54, 3) ("ipc(%s,%d): request for shutdown received. Exiting...\n", + prog, pid); + break; + } + + if (x >= 2) { + if ((buf2[x - 1] == '\n') && (buf2[x - 2] == '\r')) { + buf2[x - 2] = '\n'; + buf2[x - 1] = '\0'; + x--; + } + } + + debug(54, 5) ("ipc(%s,%d): received from child : %s\n", prog, pid, + rfc1738_escape_unescaped(buf2)); + x = send(send_fd, (const void *)buf2, x, 0); + + if ((x <= 0 && type == IPC_TCP_SOCKET) || + (x < 0 && type == IPC_UDP_SOCKET)) { + debug(54, 3) ("ipc(%s,%d): %d bytes sent to parent. Exiting...\n", + prog, pid, x); + break; + } + } + + xfree(prog); + xfree(buf2); + return 0; +} Index: squid3/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/protos.h,v retrieving revision 1.19.2.58 retrieving revision 1.19.2.59 diff -u -r1.19.2.58 -r1.19.2.59 --- squid3/src/protos.h 22 Aug 2006 10:26:05 -0000 1.19.2.58 +++ squid3/src/protos.h 3 Sep 2006 16:51:26 -0000 1.19.2.59 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.19.2.58 2006/08/22 10:26:05 serassio Exp $ + * $Id: protos.h,v 1.19.2.59 2006/09/03 16:51:26 serassio Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -676,6 +676,16 @@ SQUIDCEXTERN void strwordquote(MemBuf * mb, const char *str); +/* + * ipc.c + */ +SQUIDCEXTERN int ipcCreate(int type, + const char *prog, + const char *const args[], + const char *name, + int *rfd, + int *wfd, + void **hIpc); /* CacheDigest */ Index: squid3/src/redirect.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/redirect.cc,v retrieving revision 1.5.2.17 retrieving revision 1.5.2.18 diff -u -r1.5.2.17 -r1.5.2.18 --- squid3/src/redirect.cc 22 Aug 2006 10:26:06 -0000 1.5.2.17 +++ squid3/src/redirect.cc 3 Sep 2006 16:51:26 -0000 1.5.2.18 @@ -1,6 +1,6 @@ /* - * $Id: redirect.cc,v 1.5.2.17 2006/08/22 10:26:06 serassio Exp $ + * $Id: redirect.cc,v 1.5.2.18 2006/09/03 16:51:26 serassio Exp $ * * DEBUG: section 61 Redirector * AUTHOR: Duane Wessels @@ -37,7 +37,6 @@ #include "AuthUserRequest.h" #include "CacheManager.h" #include "Store.h" -#include "ipc.h" #include "fde.h" #include "client_side_request.h" #include "ACLChecklist.h" Index: squid3/src/unlinkd.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/unlinkd.cc,v retrieving revision 1.7.2.10 retrieving revision 1.7.2.11 diff -u -r1.7.2.10 -r1.7.2.11 --- squid3/src/unlinkd.cc 2 Sep 2006 16:02:52 -0000 1.7.2.10 +++ squid3/src/unlinkd.cc 3 Sep 2006 16:51:26 -0000 1.7.2.11 @@ -1,6 +1,6 @@ /* - * $Id: unlinkd.cc,v 1.7.2.10 2006/09/02 16:02:52 serassio Exp $ + * $Id: unlinkd.cc,v 1.7.2.11 2006/09/03 16:51:26 serassio Exp $ * * DEBUG: section 2 Unlink Daemon * AUTHOR: Duane Wessels @@ -34,7 +34,6 @@ */ #include "squid.h" -#include "ipc.h" #ifdef UNLINK_DAEMON @@ -86,9 +85,7 @@ static int unlinkd_wfd = -1; static int unlinkd_rfd = -1; -#ifdef _SQUID_MSWIN_ -static HANDLE hIpc; -#endif +static void * hIpc; static pid_t pid; #define UNLINKD_QUEUE_LIMIT 20 @@ -233,7 +230,7 @@ struct timeval slp; args[0] = "(unlinkd)"; args[1] = NULL; - IPCResult ipcRV = ipcCreate( + pid = ipcCreate( #if USE_POLL && defined(_SQUID_OSF_) /* pipes and poll() don't get along on DUNIX -DW */ IPC_STREAM, @@ -244,25 +241,16 @@ /* We currently need to use FIFO.. see below */ IPC_FIFO, #endif - Config.Program.unlinkd, - args, - "unlinkd"); + Config.Program.unlinkd, + args, + "unlinkd", + &unlinkd_rfd, + &unlinkd_wfd, + &hIpc); - if (!ipcRV.success) + if (pid < 0) fatal("Failed to create unlinkd subprocess"); - pid = ipcRV.pid; - - unlinkd_rfd = ipcRV.rfd; - - unlinkd_wfd = ipcRV.wfd; - -#ifdef _SQUID_MSWIN_ - - hIpc = ipcRV.hIpc; - -#endif - slp.tv_sec = 0; slp.tv_usec = 250000; Index: squid3/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc =================================================================== RCS file: /cvsroot/squid-sf//squid3/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -r1.1.2.3 -r1.1.2.4 --- squid3/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc 13 May 2006 12:21:10 -0000 1.1.2.3 +++ squid3/src/DiskIO/DiskDaemon/DiskdIOStrategy.cc 3 Sep 2006 16:51:27 -0000 1.1.2.4 @@ -1,6 +1,6 @@ /* - * $Id: DiskdIOStrategy.cc,v 1.1.2.3 2006/05/13 12:21:10 serassio Exp $ + * $Id: DiskdIOStrategy.cc,v 1.1.2.4 2006/09/03 16:51:27 serassio Exp $ * * DEBUG: section 79 Squid-side DISKD I/O functions. * AUTHOR: Duane Wessels @@ -153,7 +153,8 @@ void DiskdIOStrategy::init() { - int x; + int pid; + void * hIpc int rfd; int ikey; const char *args[5]; @@ -186,14 +187,15 @@ args[2] = skey2; args[3] = skey3; args[4] = NULL; - x = ipcCreate(IPC_STREAM, + pid = ipcCreate(IPC_STREAM, Config.Program.diskd, args, "diskd", &rfd, - &wfd); + &wfd, + &hIpc); - if (x < 0) + if (pid < 0) fatalf("execl: %s", Config.Program.diskd); if (rfd != wfd)