static int comm_accept_un(int fd) { int sock; struct sockaddr_un P; socklen_t Slen; Slen = sizeof(P); statCounter.syscalls.sock.accepts++; if ((sock = accept(fd, (struct sockaddr *) &P, &Slen)) < 0) { if (ignoreErrno(errno) || errno == ECONNREFUSED || errno == ECONNABORTED) { debug(191, 5) ("comm_accept_un: FD %d: %s\n", fd, xstrerror()); return COMM_NOMESSAGE; } else if (ENFILE == errno || EMFILE == errno) { debug(191, 3) ("comm_accept_un: FD %d: %s\n", fd, xstrerror()); return COMM_ERROR; } else { debug(191, 1) ("comm_accept_un: FD %d: %s\n", fd, xstrerror()); return COMM_ERROR; } } commSetCloseOnExec(sock); /* fdstat update */ fd_open(sock, FD_SOCKET, "LSCS Request"); commSetNonBlocking(sock); return sock; }
/* Create a socket. Default is blocking, stream (TCP) socket. IO_TYPE * is OR of COMM flags defined above */ int comm_open(int sock_type, int proto, u_short port, int flags) { struct sockaddr_in sa; int new_socket; /* Create socket for accepting new connections. */ if ((new_socket = socket(AF_INET, sock_type, proto)) < 0) { #ifdef DEBUG fprintf(stderr, "comm_open: socket failure\n"); #endif return (COMM_ERROR); } commSetNoLinger(new_socket); commSetReuseAddr(new_socket); memset(&sa, 0, sizeof(struct sockaddr_in)); sa.sin_family = AF_INET; sa.sin_port = htons(port); sa.sin_addr.s_addr = htonl(INADDR_ANY); if (bind(new_socket, (struct sockaddr *) &sa, sizeof(sa)) < 0) return COMM_ERROR; if (flags & COMM_NONBLOCKING) if (commSetNonBlocking(new_socket) == COMM_ERROR) return COMM_ERROR; return new_socket; }
/* Wait for an incoming connection on FD. FD should be a socket returned * from comm_listen. */ int comm_accept(int fd, struct sockaddr_in *peer, struct sockaddr_in *me) { int sock; struct sockaddr_in P; int Slen; Slen = sizeof(P); if ((sock = accept(fd, (struct sockaddr *) &P, &Slen)) < 0) { #ifdef DEBUG fprintf(stderr, "comm_accept: FD %d: accept failure\n", fd); #endif return COMM_ERROR; } if (peer) *peer = P; commSetNonBlocking(sock); return sock; }
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, 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, 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, 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 comm_open_un(int sock_type, int proto, char *path, int flags, const char *note) { int new_socket; /* Create socket for accepting new connections. */ statCounter.syscalls.sock.sockets++; if ((new_socket = socket(AF_UNIX, sock_type, proto)) < 0) { /* Increase the number of reserved fd's if calls to socket() * are failing because the open file table is full. This * limits the number of simultaneous clients */ switch (errno) { case ENFILE: case EMFILE: debug(191, 3) ("comm_open: socket failure: %s\n", xstrerror()); fdAdjustReserved(); break; default: debug(191, 0) ("comm_open: socket failure: %s\n", xstrerror()); } return -1; } debug(191, 5) ("comm_open_un: FD %d is a new UNIX socket\n", new_socket); fde *F = NULL; fd_open(new_socket, FD_SOCKET, note); F = &fd_table[new_socket]; //F->local_addr = addr; //F->tos = tos; if (!(flags & COMM_NOCLOEXEC)) commSetCloseOnExec(new_socket); if ((flags & COMM_REUSEADDR)) mod_commSetReuseAddr(new_socket); struct sockaddr_un S; memset(&S, '\0', sizeof(S)); S.sun_family = AF_UNIX; strcpy(S.sun_path, path); statCounter.syscalls.sock.binds++; if (bind(new_socket, (struct sockaddr *) &S, sizeof(S)) != 0) { debug(191, 5) ("commBind: Cannot bind socket FD %d to %s: %s\n", new_socket, path, xstrerror()); fatal("comm_open_un can not bind socket\n"); } //F->local_port = port; if (flags & COMM_NONBLOCKING) if (commSetNonBlocking(new_socket) == COMM_ERROR) return -1; return new_socket; }
static void clientRecvFd(int sock, void *data) { int retval; struct msghdr msg; struct iovec vec; char cmsgbuf[CMSG_SPACE(sizeof(int))]; struct cmsghdr *p_cmsg; char iov_buf[CACHE_WATCH_RECV_MSG_LENGTH]; vec.iov_base = iov_buf; vec.iov_len = CACHE_WATCH_RECV_MSG_LENGTH; msg.msg_name = NULL; msg.msg_namelen = 0; msg.msg_iov = &vec; msg.msg_iovlen = 1; msg.msg_control = cmsgbuf; msg.msg_controllen = sizeof(cmsgbuf); msg.msg_flags = 0; /* In case something goes wrong, set the fd to -1 before the syscall */ retval = recvmsg(sock, &msg, 0); if( retval <= 0 ) { comm_close(sock); return; } if( (p_cmsg = CMSG_FIRSTHDR(&msg)) == NULL ) { comm_close(sock); return; } if (squidWatchReply(sock, &msg, iov_buf) != -1) { comm_close(sock); return; } int fd = *((int*)CMSG_DATA(p_cmsg)); // for keep alive commSetSelect(sock, COMM_SELECT_READ, clientRecvFd, NULL, 0); // omm_close(sock); if(fd < 0) { return; } //comm_accept's jobs struct sockaddr_in peername; struct sockaddr_in sockname; socklen_t socklen; socklen = sizeof(struct sockaddr_in); memset(&peername, '\0', socklen); memset(&sockname, '\0', socklen); getpeername(fd, (struct sockaddr *)&peername, &socklen); getsockname(fd, (struct sockaddr *)&sockname, &socklen); commSetCloseOnExec(fd); fd_open(fd, FD_SOCKET, "HTTP Request"); fde *F = &fd_table[fd]; xstrncpy(F->ipaddr, xinet_ntoa(peername.sin_addr), 16); F->remote_port = htons(peername.sin_port); F->local_port = htons(sockname.sin_port); commSetNonBlocking(fd); //rest of httpAccept's jobs // //int on = 1; //if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (char *) &on, sizeof(on)) < 0) // debug(191, 0) ("commSetTcpNoDelay: FD %d: %s\n", fd, xstrerror()); //fd_table[fd].flags.nodelay = 1; #ifdef TCP_NODELAY commSetTcpNoDelay(fd); /*Fix tcp use Negale bug while send packet*/ #endif #ifdef CC_FRAMEWORK cc_call_hook_func_private_http_accept(fd); #endif debug(191, 4) ("clientRecvFd: FD %d: accepted port %d client %s:%d\n", fd, F->local_port, F->ipaddr, F->remote_port); fd_note_static(fd, "client http connect"); ConnStateData * connState = cbdataAlloc(ConnStateData); assert(Config.Sockaddr.http); connState->port = Config.Sockaddr.http; cbdataLock(connState->port); connState->peer = peername; connState->log_addr = peername.sin_addr; connState->log_addr.s_addr &= Config.Addrs.client_netmask.s_addr; connState->me = sockname; connState->fd = fd; connState->pinning.fd = -1; connState->in.buf = memAllocBuf(CLIENT_REQ_BUF_SZ, &connState->in.size); comm_add_close_handler(fd, connStateFree, connState); if (Config.onoff.log_fqdn) fqdncache_gethostbyaddr(peername.sin_addr, FQDN_LOOKUP_IF_MISS); commSetTimeout(fd, Config.Timeout.request, requestTimeout, connState); #if USE_IDENT static aclCheck_t identChecklist; identChecklist.src_addr = peername.sin_addr; identChecklist.my_addr = sockname.sin_addr; identChecklist.my_port = ntohs(sockname.sin_port); if (aclCheckFast(Config.accessList.identLookup, &identChecklist)) identStart(&sockname, &peername, clientIdentDone, connState); #endif commSetSelect(fd, COMM_SELECT_READ, clientReadRequest, connState, 0); commSetDefer(fd, clientReadDefer, connState); if (connState->port->tcp_keepalive.enabled) { commSetTcpKeepalive(fd, connState->port->tcp_keepalive.idle, connState->port->tcp_keepalive.interval, connState->port->tcp_keepalive.timeout); } clientdbEstablished(peername.sin_addr, 1); incoming_sockets_accepted++; }
void squidaio_init(void) { int i; int done_pipe[2]; squidaio_thread_t *threadp; if (squidaio_initialised) return; if (!DuplicateHandle(GetCurrentProcess(), /* pseudo handle, don't close */ GetCurrentThread(), /* pseudo handle to copy */ GetCurrentProcess(), /* pseudo handle, don't close */ &main_thread, 0, /* required access */ FALSE, /* child process's don't inherit the handle */ DUPLICATE_SAME_ACCESS)) { /* spit errors */ fatal("couldn't get current thread handle\n"); } /* Initialize request queue */ if ((request_queue.mutex = CreateMutex(NULL, /* no inheritance */ FALSE, /* start unowned (as per mutex_init) */ NULL) /* no name */ ) == NULL) { fatal("failed to create mutex\n"); } if ((request_queue.cond = CreateEvent(NULL, /* no inheritance */ FALSE, /* auto signal reset - which I think is pthreads like ? */ FALSE, /* start non signaled */ NULL) /* no name */ ) == NULL) { fatal("failed to create condition event variable.\n"); } request_queue.head = NULL; request_queue.tailp = &request_queue.head; request_queue.requests = 0; request_queue.blocked = 0; /* Initialize done queue */ if ((done_queue.mutex = CreateMutex(NULL, /* no inheritance */ FALSE, /* start unowned (as per mutex_init) */ NULL) /* no name */ ) == NULL) { fatal("failed to create mutex\n"); } if ((done_queue.cond = CreateEvent(NULL, /* no inheritance */ TRUE, /* manually signaled - which I think is pthreads like ? */ FALSE, /* start non signaled */ NULL) /* no name */ ) == NULL) { fatal("failed to create condition event variable.\n"); } done_queue.head = NULL; done_queue.tailp = &done_queue.head; done_queue.requests = 0; done_queue.blocked = 0; /* Initialize done pipe signal */ pipe(done_pipe); done_fd = done_pipe[1]; done_fd_read = done_pipe[0]; fd_open(done_fd_read, FD_PIPE, "async-io completion event: main"); fd_open(done_fd, FD_PIPE, "async-io completion event: threads"); commSetNonBlocking(done_pipe[0]); commSetNonBlocking(done_pipe[1]); commSetCloseOnExec(done_pipe[0]); commSetCloseOnExec(done_pipe[1]); commSetSelect(done_pipe[0], COMM_SELECT_READ, squidaio_fdhandler, NULL, 0); /* Create threads and get them to sit in their wait loop */ squidaio_thread_pool = memPoolCreate("aio_thread", sizeof(squidaio_thread_t)); if (squidaio_nthreads == 0) { int j = 16; for (i = 0; i < n_asyncufs_dirs; i++) { squidaio_nthreads += j; j = j * 2 / 3; if (j < 4) j = 4; } #if USE_AUFSOPS j = 6; for (i = 0; i < n_coss_dirs; i++) { squidaio_nthreads += j; j = 3; } #endif } if (squidaio_nthreads == 0) squidaio_nthreads = 16; squidaio_magic1 = squidaio_nthreads * MAGIC1_FACTOR; squidaio_magic2 = squidaio_nthreads * MAGIC2_FACTOR; for (i = 0; i < squidaio_nthreads; i++) { threadp = memPoolAlloc(squidaio_thread_pool); threadp->status = _THREAD_STARTING; threadp->current_req = NULL; threadp->requests = 0; threadp->next = threads; threads = threadp; if ((threadp->thread = CreateThread(NULL, /* no security attributes */ 0, /* use default stack size */ squidaio_thread_loop, /* thread function */ threadp, /* argument to thread function */ 0, /* use default creation flags */ &(threadp->dwThreadId)) /* returns the thread identifier */ ) == NULL) { fprintf(stderr, "Thread creation failed\n"); threadp->status = _THREAD_FAILED; continue; } /* Set the new thread priority above parent process */ SetThreadPriority(threadp->thread, THREAD_PRIORITY_ABOVE_NORMAL); } /* Create request pool */ squidaio_request_pool = memPoolCreate("aio_request", sizeof(squidaio_request_t)); squidaio_large_bufs = memPoolCreate("squidaio_large_bufs", AIO_LARGE_BUFS); squidaio_medium_bufs = memPoolCreate("squidaio_medium_bufs", AIO_MEDIUM_BUFS); squidaio_small_bufs = memPoolCreate("squidaio_small_bufs", AIO_SMALL_BUFS); squidaio_tiny_bufs = memPoolCreate("squidaio_tiny_bufs", AIO_TINY_BUFS); squidaio_micro_bufs = memPoolCreate("squidaio_micro_bufs", AIO_MICRO_BUFS); squidaio_initialised = 1; }
int ipcCreate(int type, const char *prog, char *const args[], const char *name, int *rfd, 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 if (rfd) *rfd = -1; 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 (rfd) *rfd = prfd; 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), 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)) < 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(cwfd); t3 = dup(fileno(debug_log)); assert(t1 > 2 && t2 > 2 && t3 > 2); close(crfd); close(cwfd); close(fileno(debug_log)); dup2(t1, 0); dup2(t2, 1); dup2(t3, 2); close(t1); close(t2); close(t3); #if HAVE_SETSID setsid(); #endif execvp(prog, args); debug(50, 0) ("ipcCreate: %s: %s\n", prog, xstrerror()); _exit(1); return 0; }
void helperOpenServers(helper * hlp) { char *s; char *progname; char *shortname; char *procname; const char *args[HELPER_MAX_ARGS]; char fd_note_buf[FD_DESC_SZ]; helper_server *srv; int nargs = 0; int k; int x; int rfd; int wfd; wordlist *w; if (hlp->cmdline == NULL) return; progname = hlp->cmdline->key; if ((s = strrchr(progname, '/'))) shortname = xstrdup(s + 1); else shortname = xstrdup(progname); debug(84, 1) ("helperOpenServers: Starting %d '%s' processes\n", hlp->n_to_start, shortname); procname = xmalloc(strlen(shortname) + 3); snprintf(procname, strlen(shortname) + 3, "(%s)", shortname); args[nargs++] = procname; for (w = hlp->cmdline->next; w && nargs < HELPER_MAX_ARGS; w = w->next) args[nargs++] = w->key; args[nargs++] = NULL; assert(nargs <= HELPER_MAX_ARGS); for (k = 0; k < hlp->n_to_start; k++) { getCurrentTime(); rfd = wfd = -1; x = ipcCreate(hlp->ipc_type, progname, args, shortname, &rfd, &wfd); if (x < 0) { debug(84, 1) ("WARNING: Cannot run '%s' process.\n", progname); continue; } hlp->n_running++; srv = cbdataAlloc(helper_server); srv->pid = x; srv->flags.alive = 1; srv->index = k; srv->rfd = rfd; srv->wfd = wfd; srv->buf = memAllocate(MEM_8K_BUF); srv->buf_sz = 8192; srv->offset = 0; srv->parent = hlp; cbdataLock(hlp); /* lock because of the parent backlink */ dlinkAddTail(srv, &srv->link, &hlp->servers); if (rfd == wfd) { snprintf(fd_note_buf, FD_DESC_SZ, "%s #%d", shortname, k + 1); fd_note(rfd, fd_note_buf); } else { snprintf(fd_note_buf, FD_DESC_SZ, "reading %s #%d", shortname, k + 1); fd_note(rfd, fd_note_buf); snprintf(fd_note_buf, FD_DESC_SZ, "writing %s #%d", shortname, k + 1); fd_note(wfd, fd_note_buf); } commSetNonBlocking(rfd); if (wfd != rfd) commSetNonBlocking(wfd); comm_add_close_handler(rfd, helperServerFree, srv); } hlp->last_restart = squid_curtime; safe_free(shortname); safe_free(procname); helperKickQueue(hlp); }