--------------------- PatchSet 2713 Date: 2001/08/03 15:26:37 Author: rbcollins Branch: external_logger Tag: (none) Log: First cut at helper based logging - all log files managed via Logfile abstraction are now written via a pipe based helper. Note: stderr in helpers isn't managed because cache.log (debug_log) isn't a Logfile based log. Members: src/Makefile.in:1.10->1.10.10.1 src/cf.data.pre:1.30->1.30.2.1 src/ipc.c:1.4->1.4.54.1 src/logfile.c:1.5->1.5.22.1 src/protos.h:1.30->1.30.2.1 src/structs.h:1.37->1.37.2.1 Index: squid/src/Makefile.in =================================================================== RCS file: /cvsroot/squid-sf//squid/src/Attic/Makefile.in,v retrieving revision 1.10 retrieving revision 1.10.10.1 diff -u -r1.10 -r1.10.10.1 --- squid/src/Makefile.in 5 May 2001 20:47:38 -0000 1.10 +++ squid/src/Makefile.in 3 Aug 2001 15:26:37 -0000 1.10.10.1 @@ -1,7 +1,7 @@ # # Makefile for the Squid Object Cache server # -# $Id: Makefile.in,v 1.10 2001/05/05 20:47:38 squidadm Exp $ +# $Id: Makefile.in,v 1.10.10.1 2001/08/03 15:26:37 rbcollins Exp $ # # Uncomment and customize the following to suit your needs: # @@ -32,6 +32,7 @@ PINGER_EXE = @OPT_PINGER_EXE@ CACHEMGR_EXE = cachemgr$(cgi_suffix) DISKD_EXE = diskd$(exec_suffix) +LOGD_EXE = logd$(exec_suffix) DEFAULT_PREFIX = $(prefix) DEFAULT_CONFIG_FILE = $(sysconfdir)/squid.conf @@ -45,6 +46,7 @@ DEFAULT_PINGER = $(libexecdir)/$(PINGER_EXE) DEFAULT_UNLINKD = $(libexecdir)/$(UNLINKD_EXE) DEFAULT_DISKD = $(libexecdir)/$(DISKD_EXE) +DEFAULT_LOGD = $(libexecdir)/$(LOGD_EXE) DEFAULT_ICON_DIR = $(sysconfdir)/icons DEFAULT_ERROR_DIR = $(sysconfdir)/errors DEFAULT_MIB_PATH = $(sysconfdir)/mib.txt @@ -88,7 +90,7 @@ STD_APP_LIBS = -L../lib -lmiscutil $(XTRA_LIBS) PROGS = $(SQUID_EXE) $(CLIENT_EXE) -UTILS = $(DNSSERVER_EXE) $(UNLINKD_EXE) +UTILS = $(DNSSERVER_EXE) $(UNLINKD_EXE) $(LOGD_EXE) SUID_UTILS = $(PINGER_EXE) CGIPROGS = $(CACHEMGR_EXE) OBJS = \ @@ -244,6 +246,9 @@ $(UNLINKD_EXE): unlinkd-daemon.o $(CC) $(LDFLAGS) unlinkd-daemon.o -o $@ +$(LOGD_EXE): logd.o + $(CC) $(LDFLAGS) logd.o -o $@ + unlinkd-daemon.o: unlinkd.c $(CC) -c $(CFLAGS) -DUNLINK_DAEMON $(srcdir)/unlinkd.c -o $@ @@ -276,6 +281,7 @@ s%@DEFAULT_UNLINKD@%$(DEFAULT_UNLINKD)%g;\ s%@DEFAULT_PINGER@%$(DEFAULT_PINGER)%g;\ s%@DEFAULT_DISKD@%$(DEFAULT_DISKD)%g;\ + s%@DEFAULT_LOGD@%$(DEFAULT_LOGD)%g; \ s%@DEFAULT_CACHE_LOG@%$(DEFAULT_CACHE_LOG)%g;\ s%@DEFAULT_ACCESS_LOG@%$(DEFAULT_ACCESS_LOG)%g;\ s%@DEFAULT_STORE_LOG@%$(DEFAULT_STORE_LOG)%g;\ Index: squid/src/cf.data.pre =================================================================== RCS file: /cvsroot/squid-sf//squid/src/cf.data.pre,v retrieving revision 1.30 retrieving revision 1.30.2.1 diff -u -r1.30 -r1.30.2.1 --- squid/src/cf.data.pre 28 Jul 2001 22:34:19 -0000 1.30 +++ squid/src/cf.data.pre 3 Aug 2001 15:26:38 -0000 1.30.2.1 @@ -1,6 +1,6 @@ # -# $Id: cf.data.pre,v 1.30 2001/07/28 22:34:19 squidadm Exp $ +# $Id: cf.data.pre,v 1.30.2.1 2001/08/03 15:26:38 rbcollins Exp $ # # # SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -1142,6 +1142,14 @@ Specify the location of the executable for file deletion process. DOC_END +NAME: logd_program +TYPE: string +DEFAULT: @DEFAULT_LOGD@ +LOC: Config.Program.logd +DOC_START + Specify the location of the executable for logging process. +DOC_END + NAME: pinger_program TYPE: string DEFAULT: @DEFAULT_PINGER@ Index: squid/src/ipc.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/ipc.c,v retrieving revision 1.4 retrieving revision 1.4.54.1 diff -u -r1.4 -r1.4.54.1 --- squid/src/ipc.c 12 Jan 2001 08:20:33 -0000 1.4 +++ squid/src/ipc.c 3 Aug 2001 15:26:38 -0000 1.4.54.1 @@ -1,6 +1,6 @@ /* - * $Id: ipc.c,v 1.4 2001/01/12 08:20:33 hno Exp $ + * $Id: ipc.c,v 1.4.54.1 2001/08/03 15:26:38 rbcollins Exp $ * * DEBUG: section 54 Interprocess Communication * AUTHOR: Duane Wessels @@ -257,6 +257,234 @@ } while (x < 3); t1 = dup(crfd); t2 = dup(cwfd); +// if (!Config.Log.log) + t3 = dup(fileno(debug_log)); +// else + // t3 = dup(Config.Log.log->logfd); + assert(t1 > 2 && t2 > 2 && t3 > 2); + close(crfd); + close(cwfd); +// if (!Config.Log.log) + 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 (x = 3; x < SQUID_MAXFD; x++) + close(x); +#if HAVE_SETSID + setsid(); +#endif + execvp(prog, args); + debug_log = fdopen(2, "a+"); + debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror()); + _exit(1); + return 0; +} + +/* create a oneway ipc, used for logging. ipcout becomes the child process stdout */ +int +ipcCreateOneWay(int type, const char *prog, char *const args[], const char *name, int ipcout, int *wfd) +{ + pid_t pid; + struct sockaddr_in CS; + struct sockaddr_in PS; + int crfd = -1; + int prfd = -1; + int cwfd = -1; + int pwfd = -1; + int fd; + int t1, t2, t3; + socklen_t len; + int tmp_s; +#if HAVE_PUTENV + char *env_str; +#endif + int x; + +#if HAVE_POLL && defined(_SQUID_OSF_) + assert(type != IPC_FIFO); +#endif + + assert (ipcout > 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; + } + fd_open(prfd = p2c[0], FD_PIPE, "IPC FIFO Parent Read"); + fd_open(cwfd = p2c[1], FD_PIPE, "IPC FIFO Child Write"); + fd_open(crfd = c2p[0], FD_PIPE, "IPC FIFO Child Read"); + fd_open(pwfd = c2p[1], FD_PIPE, "IPC FIFO Parent Write"); + } 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 (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(50, 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(50, 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(50, 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(); + if ((pid = fork()) < 0) { + debug(50, 1) ("ipcCreate: fork: %s\n", xstrerror()); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } + if (pid > 0) { /* parent */ + /* close shared socket with child */ + comm_close(crfd); + if (cwfd != crfd) + comm_close(cwfd); + cwfd = crfd = -1; + if (type == IPC_TCP_SOCKET || type == IPC_UDP_SOCKET) { + if (comm_connect_addr(pwfd, &CS) == COMM_ERROR) + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } + memset(hello_buf, '\0', HELLO_BUF_SZ); + if (type == IPC_UDP_SOCKET) + x = recv(prfd, hello_buf, HELLO_BUF_SZ - 1, 0); + else + x = read(prfd, hello_buf, HELLO_BUF_SZ - 1); + if (x < 0) { + debug(50, 0) ("ipcCreate: PARENT: hello read test failed\n"); + debug(50, 0) ("--> read: %s\n", xstrerror()); + 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)); + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } + commSetTimeout(prfd, -1, NULL, NULL); + commSetNonBlocking(prfd); + commSetNonBlocking(pwfd); + if (wfd) + *wfd = pwfd; + fd_table[prfd].flags.ipc = 1; + fd_table[pwfd].flags.ipc = 1; + return pwfd; + } + /* child */ + no_suid(); /* give up extra priviliges */ + /* close shared socket with parent */ + close(prfd); + if (pwfd != prfd) + close(pwfd); + pwfd = prfd = -1; + + if (type == IPC_TCP_SOCKET) { + debug(54, 3) ("ipcCreate: calling accept on FD %d\n", crfd); + if ((fd = accept(crfd, NULL, NULL)) < 0) { + debug(50, 0) ("ipcCreate: FD %d accept: %s\n", crfd, xstrerror()); + _exit(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, &PS) == COMM_ERROR) + return ipcCloseAllFD(prfd, pwfd, crfd, cwfd); + } + if (type == IPC_UDP_SOCKET) { + x = send(cwfd, hello_string, strlen(hello_string) + 1, 0); + 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); + } + } 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); + } + } +#if HAVE_PUTENV + env_str = xcalloc((tmp_s = strlen(Config.debugOptions) + 32), 1); + snprintf(env_str, tmp_s, "SQUID_DEBUG=%s", Config.debugOptions); + putenv(env_str); +#endif + /* + * This double-dup stuff avoids problems when one of + * crfd, cwfd, or debug_log are in the rage 0-2. + */ + do { + x = open(_PATH_DEVNULL, 0, 0444); + if (x > -1) + commSetCloseOnExec(x); + } while (x < 3); + t1 = dup(crfd); + t2 = dup(ipcout); t3 = dup(fileno(debug_log)); assert(t1 > 2 && t2 > 2 && t3 > 2); close(crfd); @@ -280,3 +508,4 @@ _exit(1); return 0; } + Index: squid/src/logfile.c =================================================================== RCS file: /cvsroot/squid-sf//squid/src/logfile.c,v retrieving revision 1.5 retrieving revision 1.5.22.1 diff -u -r1.5 -r1.5.22.1 --- squid/src/logfile.c 17 Apr 2001 21:20:20 -0000 1.5 +++ squid/src/logfile.c 3 Aug 2001 15:26:38 -0000 1.5.22.1 @@ -40,6 +40,7 @@ logfileOpen(const char *path, size_t bufsz, int fatal_flag) { int fd; + int x; Logfile *lf; fd = file_open(path, O_WRONLY | O_CREAT | O_TEXT); if (DISK_ERROR == fd) { @@ -58,7 +59,6 @@ } } lf = xcalloc(1, sizeof(*lf)); - lf->fd = fd; if (fatal_flag) lf->flags.fatal = 1; xstrncpy(lf->path, path, MAXPATHLEN); @@ -66,6 +66,21 @@ lf->buf = xmalloc(bufsz); lf->bufsz = bufsz; } + lf->filefd = fd; + x = ipcCreateOneWay( +#if HAVE_POLL && defined(_SQUID_OSF_) + /* pipes and poll() don't get along on DUNIX -DW */ + IPC_TCP_SOCKET, +#else + IPC_FIFO, +#endif + Config.Program.logd, + NULL, + "logd", + lf->filefd, + &lf->logfd); + if (x < 0) + fatalf("execl %s failed!\n", Config.Program.logd); return lf; } @@ -73,9 +88,10 @@ logfileClose(Logfile * lf) { logfileFlush(lf); - file_close(lf->fd); + file_close(lf->filefd); if (lf->buf) xfree(lf->buf); + comm_close(lf->logfd); xfree(lf); } @@ -83,7 +99,7 @@ logfileRotate(Logfile * lf) { struct stat sb; - int i; + int i,x; char from[MAXPATHLEN]; char to[MAXPATHLEN]; assert(lf->path); @@ -102,17 +118,33 @@ } /* Rotate the current log to .0 */ logfileFlush(lf); - file_close(lf->fd); /* always close */ + /* always close */ + file_close(lf->filefd); + comm_close(lf->logfd); if (Config.Log.rotateNumber > 0) { snprintf(to, MAXPATHLEN, "%s.%d", lf->path, 0); xrename(lf->path, to); } /* Reopen the log. It may have been renamed "manually" */ - lf->fd = file_open(lf->path, O_WRONLY | O_CREAT | O_TEXT); - if (DISK_ERROR == lf->fd && lf->flags.fatal) { + lf->filefd = file_open(lf->path, O_WRONLY | O_CREAT | O_TEXT); + if (DISK_ERROR == lf->filefd && lf->flags.fatal) { debug(50, 1) ("logfileRotate: %s: %s\n", lf->path, xstrerror()); fatalf("Cannot open %s: %s", lf->path, xstrerror()); } + x = ipcCreateOneWay( +#if HAVE_POLL && defined(_SQUID_OSF_) + /* pipes and poll() don't get along on DUNIX -DW */ + IPC_TCP_SOCKET, +#else + IPC_FIFO, +#endif + Config.Program.logd, + NULL, + "logd", + lf->filefd, + &lf->logfd); + if (x < 0) + fatalf("execl %s failed!\n", Config.Program.logd); } void @@ -178,8 +210,9 @@ logfileWriteWrapper(Logfile * lf, const void *buf, size_t len) { int s; - s = write(lf->fd, buf, len); - fd_bytes(lf->fd, s, FD_WRITE); + /* sync io to ensure logs get written - this could (and probably should) use comm_write */ + s = write(lf->logfd, buf, len); + fd_bytes(lf->logfd, s, FD_WRITE); if (s == len) return; if (!lf->flags.fatal) Index: squid/src/protos.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/protos.h,v retrieving revision 1.30 retrieving revision 1.30.2.1 diff -u -r1.30 -r1.30.2.1 --- squid/src/protos.h 28 Jul 2001 22:34:19 -0000 1.30 +++ squid/src/protos.h 3 Aug 2001 15:26:38 -0000 1.30.2.1 @@ -1,6 +1,6 @@ /* - * $Id: protos.h,v 1.30 2001/07/28 22:34:19 squidadm Exp $ + * $Id: protos.h,v 1.30.2.1 2001/08/03 15:26:38 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -1190,6 +1190,7 @@ const char *name, int *rfd, int *wfd); +extern int ipcCreateOneWay(int, const char *, char *const *, const char *, int, int *); /* CacheDigest */ extern CacheDigest *cacheDigestCreate(int capacity, int bpe); Index: squid/src/structs.h =================================================================== RCS file: /cvsroot/squid-sf//squid/src/structs.h,v retrieving revision 1.37 retrieving revision 1.37.2.1 diff -u -r1.37 -r1.37.2.1 --- squid/src/structs.h 28 Jul 2001 22:34:19 -0000 1.37 +++ squid/src/structs.h 3 Aug 2001 15:26:38 -0000 1.37.2.1 @@ -1,6 +1,6 @@ /* - * $Id: structs.h,v 1.37 2001/07/28 22:34:19 squidadm Exp $ + * $Id: structs.h,v 1.37.2.1 2001/08/03 15:26:38 rbcollins Exp $ * * * SQUID Web Proxy Cache http://www.squid-cache.org/ @@ -446,6 +446,7 @@ char *unlinkd; #endif char *diskd; + char *logd; } Program; #if USE_DNSSERVERS int dnsChildren; @@ -2104,7 +2105,8 @@ }; struct _Logfile { - int fd; + int filefd; + int logfd; char path[MAXPATHLEN]; char *buf; size_t bufsz;