Print this page
XXXX update sendmail to 8.14.9

*** 1,7 **** /* ! * Copyright (c) 2003-2004, 2007, 2009 Sendmail, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution. --- 1,7 ---- /* ! * Copyright (c) 2003-2004, 2007, 2009-2012 Proofpoint, Inc. and its suppliers. * All rights reserved. * * By using this file, you agree to the terms and conditions set * forth in the LICENSE file which can be found at the top level of * the sendmail distribution.
*** 9,19 **** * Contributed by Jose Marcio Martins da Cruz - Ecole des Mines de Paris * Jose-Marcio.Martins@ensmp.fr */ #include <sm/gen.h> ! SM_RCSID("@(#)$Id: worker.c,v 8.17 2009/06/15 15:34:54 ca Exp $") #include "libmilter.h" #if _FFR_WORKERS_POOL --- 9,19 ---- * Contributed by Jose Marcio Martins da Cruz - Ecole des Mines de Paris * Jose-Marcio.Martins@ensmp.fr */ #include <sm/gen.h> ! SM_RCSID("@(#)$Id: worker.c,v 8.25 2013-11-22 20:51:37 ca Exp $") #include "libmilter.h" #if _FFR_WORKERS_POOL
*** 139,149 **** sm_errstring(r)); \ } while (0) #if POOL_DEBUG # define POOL_LEV_DPRINTF(lev, x) \ ! do { \ if ((lev) < ctx->ctx_dbg) \ sm_dprintf x; \ } while (0) #else /* POOL_DEBUG */ # define POOL_LEV_DPRINTF(lev, x) --- 139,150 ---- sm_errstring(r)); \ } while (0) #if POOL_DEBUG # define POOL_LEV_DPRINTF(lev, x) \ ! do \ ! { \ if ((lev) < ctx->ctx_dbg) \ sm_dprintf x; \ } while (0) #else /* POOL_DEBUG */ # define POOL_LEV_DPRINTF(lev, x)
*** 163,173 **** mi_start_session(ctx) SMFICTX_PTR ctx; { static long id = 0; ! SM_ASSERT(Tskmgr.tm_signature == TM_SIGNATURE); SM_ASSERT(ctx != NULL); POOL_LEV_DPRINTF(4, ("PIPE r=[%d] w=[%d]", RD_PIPE, WR_PIPE)); TASKMGR_LOCK(); if (mi_list_add_ctx(ctx) != MI_SUCCESS) --- 164,176 ---- mi_start_session(ctx) SMFICTX_PTR ctx; { static long id = 0; ! /* this can happen if the milter is shutting down */ ! if (Tskmgr.tm_signature != TM_SIGNATURE) ! return MI_FAILURE; SM_ASSERT(ctx != NULL); POOL_LEV_DPRINTF(4, ("PIPE r=[%d] w=[%d]", RD_PIPE, WR_PIPE)); TASKMGR_LOCK(); if (mi_list_add_ctx(ctx) != MI_SUCCESS)
*** 214,223 **** --- 217,261 ---- return MI_SUCCESS; } /* + ** NONBLOCKING -- set nonblocking mode for a file descriptor. + ** + ** Parameters: + ** fd -- file descriptor + ** name -- name for (error) logging + ** + ** Returns: + ** MI_SUCCESS/MI_FAILURE + */ + + static int + nonblocking(int fd, const char *name) + { + int r; + + errno = 0; + r = fcntl(fd, F_GETFL, 0); + if (r == -1) + { + smi_log(SMI_LOG_ERR, "fcntl(%s, F_GETFL)=%s", + name, sm_errstring(errno)); + return MI_FAILURE; + } + errno = 0; + r = fcntl(fd, F_SETFL, r | O_NONBLOCK); + if (r == -1) + { + smi_log(SMI_LOG_ERR, "fcntl(%s, F_SETFL, O_NONBLOCK)=%s", + name, sm_errstring(errno)); + return MI_FAILURE; + } + return MI_SUCCESS; + } + + /* ** MI_POOL_CONTROLER_INIT -- Launch the worker pool controller ** Must be called before starting sessions. ** ** Parameters: ** none
*** 244,253 **** --- 282,297 ---- { smi_log(SMI_LOG_ERR, "can't create event pipe: %s", sm_errstring(errno)); return MI_FAILURE; } + r = nonblocking(WR_PIPE, "WR_PIPE"); + if (r != MI_SUCCESS) + return r; + r = nonblocking(RD_PIPE, "RD_PIPE"); + if (r != MI_SUCCESS) + return r; (void) smutex_init(&Tskmgr.tm_w_mutex); (void) scond_init(&Tskmgr.tm_w_cond); /* Launch the pool controller */
*** 332,342 **** lastcheck = time(NULL); for (;;) { SMFICTX_PTR ctx; ! int nfd, rfd, i; time_t now; POOL_LEV_DPRINTF(4, ("Let's %s again...", WAITFN)); if (mi_stop() != MILTER_CONT) --- 376,386 ---- lastcheck = time(NULL); for (;;) { SMFICTX_PTR ctx; ! int nfd, r, i; time_t now; POOL_LEV_DPRINTF(4, ("Let's %s again...", WAITFN)); if (mi_stop() != MILTER_CONT)
*** 453,475 **** } TASKMGR_UNLOCK(); /* Everything is ready, let's wait for an event */ ! rfd = poll(pfd, nfd, POLL_TIMEOUT); POOL_LEV_DPRINTF(4, ("%s returned: at epoch %d value %d", WAITFN, now, nfd)); /* timeout */ ! if (rfd == 0) continue; rebuild_set = true; /* error */ ! if (rfd < 0) { if (errno == EINTR) continue; pcnt++; smi_log(SMI_LOG_ERR, --- 497,519 ---- } TASKMGR_UNLOCK(); /* Everything is ready, let's wait for an event */ ! r = poll(pfd, nfd, POLL_TIMEOUT); POOL_LEV_DPRINTF(4, ("%s returned: at epoch %d value %d", WAITFN, now, nfd)); /* timeout */ ! if (r == 0) continue; rebuild_set = true; /* error */ ! if (r < 0) { if (errno == EINTR) continue; pcnt++; smi_log(SMI_LOG_ERR,
*** 477,486 **** --- 521,531 ---- WAITFN, sm_errstring(errno), pcnt >= MAX_FAILS_S ? "abort" : "try again"); if (pcnt >= MAX_FAILS_S) goto err; + continue; } pcnt = 0; /* something happened */ for (i = 0; i < nfd; i++)
*** 490,530 **** POOL_LEV_DPRINTF(4, ("%s event on pfd[%d/%d]=%d ", WAITFN, i, nfd, WAIT_FD(i))); ! /* has a worker signaled an end of task ? */ if (WAIT_FD(i) == RD_PIPE) { ! char evt = 0; ! int r = 0; POOL_LEV_DPRINTF(4, ("PIPE WILL READ evt = %08X %08X", pfd[i].events, pfd[i].revents)); ! if ((pfd[i].revents & MI_POLL_RD_FLAGS) != 0) { ! r = read(RD_PIPE, &evt, sizeof(evt)); ! if (r == sizeof(evt)) ! { ! /* Do nothing */ } - } POOL_LEV_DPRINTF(4, ("PIPE DONE READ i=[%d] fd=[%d] r=[%d] evt=[%d]", ! i, RD_PIPE, r, evt)); if ((pfd[i].revents & ~MI_POLL_RD_FLAGS) != 0) { /* Exception handling */ } continue; } ! /* no ! sendmail wants to send a command */ SM_TAILQ_FOREACH(ctx, &WRK_CTX_HEAD, ctx_link) { if (ctx->ctx_wstate != WKST_WAITING) continue; --- 535,578 ---- POOL_LEV_DPRINTF(4, ("%s event on pfd[%d/%d]=%d ", WAITFN, i, nfd, WAIT_FD(i))); ! /* has a worker signaled an end of task? */ if (WAIT_FD(i) == RD_PIPE) { ! char evts[256]; ! ssize_t r; POOL_LEV_DPRINTF(4, ("PIPE WILL READ evt = %08X %08X", pfd[i].events, pfd[i].revents)); ! r = 1; ! while ((pfd[i].revents & MI_POLL_RD_FLAGS) != 0 ! && r != -1) { ! r = read(RD_PIPE, evts, sizeof(evts)); } POOL_LEV_DPRINTF(4, ("PIPE DONE READ i=[%d] fd=[%d] r=[%d] evt=[%d]", ! i, RD_PIPE, (int) r, evts[0])); if ((pfd[i].revents & ~MI_POLL_RD_FLAGS) != 0) { /* Exception handling */ } continue; } ! /* ! ** Not the pipe for workers waking us, ! ** so must be something on an MTA connection. ! */ ! ! TASKMGR_LOCK(); SM_TAILQ_FOREACH(ctx, &WRK_CTX_HEAD, ctx_link) { if (ctx->ctx_wstate != WKST_WAITING) continue;
*** 532,542 **** ("Checking context sd=%d - fd=%d ", ctx->ctx_sd , WAIT_FD(i))); if (ctx->ctx_sd == pfd[i].fd) { - TASKMGR_LOCK(); POOL_LEV_DPRINTF(4, ("TASK: found %d for fd[%d]=%d", ctx->ctx_sid, i, WAIT_FD(i))); --- 580,589 ----
*** 548,561 **** else { ctx->ctx_wstate = WKST_RUNNING; LAUNCH_WORKER(ctx); } - TASKMGR_UNLOCK(); break; } } POOL_LEV_DPRINTF(4, ("TASK %s FOUND - Checking PIPE for fd[%d]", ctx != NULL ? "" : "NOT", WAIT_FD(i))); } --- 595,608 ---- else { ctx->ctx_wstate = WKST_RUNNING; LAUNCH_WORKER(ctx); } break; } } + TASKMGR_UNLOCK(); POOL_LEV_DPRINTF(4, ("TASK %s FOUND - Checking PIPE for fd[%d]", ctx != NULL ? "" : "NOT", WAIT_FD(i))); }
*** 564,582 **** --- 611,638 ---- err: if (pfd != NULL) free(pfd); Tskmgr.tm_signature = 0; + #if 0 + /* + ** Do not clean up ctx -- it can cause double-free()s. + ** The program is shutting down anyway, so it's not worth the trouble. + ** There is a more complex solution that prevents race conditions + ** while accessing ctx, but that's maybe for a later version. + */ + for (;;) { SMFICTX_PTR ctx; ctx = SM_TAILQ_FIRST(&WRK_CTX_HEAD); if (ctx == NULL) break; mi_close_session(ctx); } + #endif (void) smutex_destroy(&Tskmgr.tm_w_mutex); (void) scond_destroy(&Tskmgr.tm_w_cond); return NULL;