diff --git a/rsyslog-3.21.10-HUPisRestart.patch b/rsyslog-3.21.10-HUPisRestart.patch new file mode 100644 index 0000000..29fda10 --- /dev/null +++ b/rsyslog-3.21.10-HUPisRestart.patch @@ -0,0 +1,485 @@ +From 5f83b6a346faca241b310c7d5be2b7eacc6239f9 Mon Sep 17 00:00:00 2001 +From: Rainer Gerhards +Date: Thu, 23 Oct 2008 14:46:47 +0200 +Subject: [PATCH] added configuration directive "HUPisRestart" + +...which enables to configure HUP to be either a full restart +or "just" a leightweight way to close open files +--- + ChangeLog | 3 ++ + action.c | 33 ++++++++++++++++++++++ + action.h | 1 + + doc/rsyslog_conf.html | 5 +++ + runtime/glbl.c | 5 +++ + runtime/glbl.h | 1 + + runtime/module-template.h | 31 +++++++++++++++++++- + runtime/modules.c | 5 +++ + runtime/modules.h | 1 + + tools/omfile.c | 68 ++++++++++++++++++++++++++++++++------------ + tools/syslogd.c | 57 ++++++++++++++++++++++++++++++++----- + 11 files changed, 181 insertions(+), 29 deletions(-) + +diff --git a/ChangeLog b/ChangeLog +index db6abcf..d1bceeb 100644 +--- a/ChangeLog ++++ b/ChangeLog +@@ -1,3 +1,6 @@ ++- added configuration directive "HUPisRestart" which enables to configure ++ HUP to be either a full restart or "just" a leightweight way to ++ close open files. + --------------------------------------------------------------------------- + Version 3.21.10 [BETA] (rgerhards), 2009-02-02 + - bugfix: inconsistent use of mutex/atomic operations could cause segfault +diff --git a/action.c b/action.c +index 5c5bdbe..d257290 100644 +--- a/action.c ++++ b/action.c +@@ -498,6 +498,39 @@ finalize_it: + } + #pragma GCC diagnostic warning "-Wempty-body" + ++ ++/* call the HUP handler for a given action, if such a handler is defined. The ++ * action mutex is locked, because the HUP handler most probably needs to modify ++ * some internal state information. ++ * rgerhards, 2008-10-22 ++ */ ++#pragma GCC diagnostic ignored "-Wempty-body" ++rsRetVal ++actionCallHUPHdlr(action_t *pAction) ++{ ++ DEFiRet; ++ int iCancelStateSave; ++ ++ ASSERT(pAction != NULL); ++ dbgprintf("Action %p checks HUP hdlr: %p\n", pAction, pAction->pMod->doHUP); ++ ++ if(pAction->pMod->doHUP == NULL) { ++ FINALIZE; /* no HUP handler, so we are done ;) */ ++ } ++ ++ pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &iCancelStateSave); ++ d_pthread_mutex_lock(&pAction->mutActExec); ++ pthread_cleanup_push(mutexCancelCleanup, &pAction->mutActExec); ++ pthread_setcancelstate(iCancelStateSave, NULL); ++ CHKiRet(pAction->pMod->doHUP(pAction->pModData)); ++ pthread_cleanup_pop(1); /* unlock mutex */ ++ ++finalize_it: ++ RETiRet; ++} ++#pragma GCC diagnostic warning "-Wempty-body" ++ ++ + /* set the action message queue mode + * TODO: probably move this into queue object, merge with MainMsgQueue! + * rgerhards, 2008-01-28 +diff --git a/action.h b/action.h +index d26d15b..8d9d510 100644 +--- a/action.h ++++ b/action.h +@@ -85,6 +85,7 @@ rsRetVal actionSetGlobalResumeInterval(int iNewVal); + rsRetVal actionDoAction(action_t *pAction); + rsRetVal actionCallAction(action_t *pAction, msg_t *pMsg); + rsRetVal actionWriteToAction(action_t *pAction); ++rsRetVal actionCallHUPHdlr(action_t *pAction); + rsRetVal actionClassInit(void); + rsRetVal addAction(action_t **ppAction, modInfo_t *pMod, void *pModData, omodStringRequest_t *pOMSR, int bSuspended); + +diff --git a/doc/rsyslog_conf.html b/doc/rsyslog_conf.html +index 8947165..2698a71 100644 +--- a/doc/rsyslog_conf.html ++++ b/doc/rsyslog_conf.html +@@ -175,6 +175,11 @@ default 60000 (1 minute)] +
  • $GssForwardServiceName
  • +
  • $GssListenServiceName
  • +
  • $GssMode
  • ++
  • $HUPisRestart [on/off] - if set to on, a HUP is a full daemon restart. This means any queued messages are discarded (depending ++on queue configuration, of course) all modules are unloaded and reloaded. This mode keeps compatible with sysklogd, but is ++not recommended for use with rsyslog. To do a full restart, simply stop and start the daemon. The default is "on" for ++compatibility reasons. If it is set to "off", a HUP will only close open files. This is a much quicker action and usually ++the only one that is needed e.g. for log rotation. It is recommended to set the setting to "off".
  • +
  • $IncludeConfig
  • MainMsgQueueCheckpointInterval <number>
  • +
  • $MainMsgQueueDequeueSlowdown <number> [number + is timeout in microseconds (1000000us is 1sec!), +diff --git a/runtime/glbl.c b/runtime/glbl.c +index 1114fcd..67509e9 100644 +--- a/runtime/glbl.c ++++ b/runtime/glbl.c +@@ -52,6 +52,7 @@ DEFobjStaticHelpers + */ + static uchar *pszWorkDir = NULL; + static int iMaxLine = 2048; /* maximum length of a syslog message */ ++static int bHUPisRestart = 1; /* should SIGHUP cause a full system restart? */ + static int iDefPFFamily = PF_UNSPEC; /* protocol family (IPv4, IPv6 or both) */ + static int bDropMalPTRMsgs = 0;/* Drop messages which have malicious PTR records during DNS lookup */ + static int option_DisallowWarning = 1; /* complain if message from disallowed sender is received */ +@@ -86,6 +87,7 @@ static dataType Get##nameFunc(void) \ + } + + SIMP_PROP(MaxLine, iMaxLine, int) ++SIMP_PROP(HUPisRestart, bHUPisRestart, int) + SIMP_PROP(DefPFFamily, iDefPFFamily, int) /* note that in the future we may check the family argument */ + SIMP_PROP(DropMalPTRMsgs, bDropMalPTRMsgs, int) + SIMP_PROP(Option_DisallowWarning, option_DisallowWarning, int) +@@ -173,6 +175,7 @@ CODESTARTobjQueryInterface(glbl) + pIf->Get##name = Get##name; \ + pIf->Set##name = Set##name; + SIMP_PROP(MaxLine); ++ SIMP_PROP(HUPisRestart); + SIMP_PROP(DefPFFamily); + SIMP_PROP(DropMalPTRMsgs); + SIMP_PROP(Option_DisallowWarning); +@@ -216,6 +219,7 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a + pszWorkDir = NULL; + } + bDropMalPTRMsgs = 0; ++ bHUPisRestart = 1; + return RS_RET_OK; + } + +@@ -235,6 +239,7 @@ BEGINAbstractObjClassInit(glbl, 1, OBJ_IS_CORE_MODULE) /* class, version */ + CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercafile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCAF, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdriverkeyfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrKeyFile, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"defaultnetstreamdrivercertfile", 0, eCmdHdlrGetWord, NULL, &pszDfltNetstrmDrvrCertFile, NULL)); ++ CHKiRet(regCfSysLineHdlr((uchar *)"hupisrestart", 0, eCmdHdlrBinary, NULL, &bHUPisRestart, NULL)); + CHKiRet(regCfSysLineHdlr((uchar *)"resetconfigvariables", 1, eCmdHdlrCustomHandler, resetConfigVariables, NULL, NULL)); + ENDObjClassInit(glbl) + +diff --git a/runtime/glbl.h b/runtime/glbl.h +index 0c83bdd..bcb9ad2 100644 +--- a/runtime/glbl.h ++++ b/runtime/glbl.h +@@ -41,6 +41,7 @@ BEGINinterface(glbl) /* name must also be changed in ENDinterface macro! */ + dataType (*Get##name)(void); \ + rsRetVal (*Set##name)(dataType); + SIMP_PROP(MaxLine, int) ++ SIMP_PROP(HUPisRestart, int) + SIMP_PROP(DefPFFamily, int) + SIMP_PROP(DropMalPTRMsgs, int) + SIMP_PROP(Option_DisallowWarning, int) +diff --git a/runtime/module-template.h b/runtime/module-template.h +index eb39b58..6f7d877 100644 +--- a/runtime/module-template.h ++++ b/runtime/module-template.h +@@ -481,6 +481,33 @@ static rsRetVal afterRun(void)\ + } + + +-/* +- * vi:set ai: ++/* doHUP() ++ * This function is optional. Currently, it is available to output plugins ++ * only, but may be made available to other types of plugins in the future. ++ * A plugin does not need to define this entry point. If if does, it gets ++ * called when a non-restart type of HUP is done. A plugin should register ++ * this function so that it can close files, connection or other ressources ++ * on HUP - if it can be assume the user wanted to do this as a part of HUP ++ * processing. Note that the name "HUP" has historical reasons, it stems back ++ * to the infamous SIGHUP which was sent to restart a syslogd. We still retain ++ * that legacy, but may move this to a different signal. ++ * rgerhards, 2008-10-22 ++ */ ++#define CODEqueryEtryPt_doHUP \ ++ else if(!strcmp((char*) name, "doHUP")) {\ ++ *pEtryPoint = doHUP;\ ++ } ++#define BEGINdoHUP \ ++static rsRetVal doHUP(instanceData __attribute__((unused)) *pData)\ ++{\ ++ DEFiRet; ++ ++#define CODESTARTdoHUP ++ ++#define ENDdoHUP \ ++ RETiRet;\ ++} ++ ++ ++/* vim:set ai: + */ +diff --git a/runtime/modules.c b/runtime/modules.c +index d5730ed..169d234 100644 +--- a/runtime/modules.c ++++ b/runtime/modules.c +@@ -347,6 +347,7 @@ static rsRetVal + doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_t*), uchar *name, void *pModHdlr) + { + DEFiRet; ++ rsRetVal localRet; + modInfo_t *pNew = NULL; + rsRetVal (*modGetType)(eModType_t *pType); + +@@ -391,6 +392,10 @@ doModInit(rsRetVal (*modInit)(int, int*, rsRetVal(**)(), rsRetVal(*)(), modInfo_ + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"parseSelectorAct", &pNew->mod.om.parseSelectorAct)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"isCompatibleWithFeature", &pNew->isCompatibleWithFeature)); + CHKiRet((*pNew->modQueryEtryPt)((uchar*)"tryResume", &pNew->tryResume)); ++ /* try load optional interfaces */ ++ localRet = (*pNew->modQueryEtryPt)((uchar*)"doHUP", &pNew->doHUP); ++ if(localRet != RS_RET_OK && localRet != RS_RET_MODULE_ENTRY_POINT_NOT_FOUND) ++ ABORT_FINALIZE(localRet); + break; + case eMOD_LIB: + break; +diff --git a/runtime/modules.h b/runtime/modules.h +index 7d34bcf..77bc5d1 100644 +--- a/runtime/modules.h ++++ b/runtime/modules.h +@@ -88,6 +88,7 @@ typedef struct modInfo_s { + rsRetVal (*tryResume)(void*);/* called to see if module actin can be resumed now */ + rsRetVal (*modExit)(void); /* called before termination or module unload */ + rsRetVal (*modGetID)(void **); /* get its unique ID from module */ ++ rsRetVal (*doHUP)(void *); /* non-restart type HUP handler */ + /* below: parse a configuration line - return if processed + * or not. If not, must be parsed to next module. + */ +diff --git a/tools/omfile.c b/tools/omfile.c +index d76e24a..5b661cb 100644 +--- a/tools/omfile.c ++++ b/tools/omfile.c +@@ -244,7 +244,6 @@ static rsRetVal cflineParseOutchannel(instanceData *pData, uchar* p, omodStringR + */ + pData->f_sizeLimitCmd = (char*) pOch->cmdOnSizeLimit; + +-RUNLOG_VAR("%p", pszTplName); + iRet = cflineParseTemplateName(&p, pOMSR, iEntry, iTplOpts, + (pszTplName == NULL) ? (uchar*)"RSYSLOG_FileFormat" : pszTplName); + +@@ -349,9 +348,11 @@ finalize_it: + } + + +-/* This function frees the dynamic file name cache. ++/* This function frees all dynamic file name cache entries and closes the ++ * relevant files. Part of Shutdown and HUP processing. ++ * rgerhards, 2008-10-23 + */ +-static void dynaFileFreeCache(instanceData *pData) ++static inline void dynaFileFreeCacheEntries(instanceData *pData) + { + register int i; + ASSERT(pData != NULL); +@@ -360,17 +361,36 @@ static void dynaFileFreeCache(instanceData *pData) + for(i = 0 ; i < pData->iCurrCacheSize ; ++i) { + dynaFileDelCacheEntry(pData->dynCache, i, 1); + } ++ ENDfunc; ++} ++ ++ ++/* This function frees the dynamic file name cache. ++ */ ++static void dynaFileFreeCache(instanceData *pData) ++{ ++ ASSERT(pData != NULL); + ++ BEGINfunc; ++ dynaFileFreeCacheEntries(pData); + if(pData->dynCache != NULL) + d_free(pData->dynCache); + ENDfunc; + } + + +-/* This is a shared code for both static and dynamic files. ++/* This is now shared code for all types of files. It simply prepares ++ * file access, which, among others, means the the file wil be opened ++ * and any directories in between will be created (based on config, of ++ * course). -- rgerhards, 2008-10-22 + */ + static void prepareFile(instanceData *pData, uchar *newFileName) + { ++ if(pData->fileType == eTypePIPE) { ++ pData->fd = open((char*) pData->f_fname, O_RDWR|O_NONBLOCK); ++ FINALIZE; /* we are done in this case */ ++ } ++ + if(access((char*)newFileName, F_OK) == 0) { + /* file already exists */ + pData->fd = open((char*) newFileName, O_WRONLY|O_APPEND|O_CREAT|O_NOCTTY, +@@ -413,6 +433,12 @@ static void prepareFile(instanceData *pData, uchar *newFileName) + } + } + } ++finalize_it: ++ if((pData->fd) != 0 && isatty(pData->fd)) { ++ dbgprintf("file %d is a tty file\n", pData->fd); ++ pData->fileType = eTypeTTY; ++ untty(); ++ } + } + + +@@ -537,6 +563,8 @@ static rsRetVal writeFile(uchar **ppString, unsigned iMsgOpts, instanceData *pDa + if(pData->bDynamicName) { + if(prepareDynFile(pData, ppString[1], iMsgOpts) != 0) + ABORT_FINALIZE(RS_RET_ERR); ++ } else if(pData->fd == -1) { ++ prepareFile(pData, pData->f_fname); + } + + /* create the message based on format specified */ +@@ -642,12 +670,7 @@ ENDtryResume + BEGINdoAction + CODESTARTdoAction + dbgprintf(" (%s)\n", pData->f_fname); +- /* pData->fd == -1 is an indicator that the we couldn't +- * open the file at startup. For dynaFiles, this is ok, +- * all others are doomed. +- */ +- if(pData->bDynamicName || (pData->fd != -1)) +- iRet = writeFile(ppString, iMsgOpts, pData); ++ iRet = writeFile(ppString, iMsgOpts, pData); + ENDdoAction + + +@@ -764,11 +787,7 @@ CODESTARTparseSelectorAct + pData->dirUID = dirUID; + pData->dirGID = dirGID; + +- if(pData->fileType == eTypePIPE) { +- pData->fd = open((char*) pData->f_fname, O_RDWR|O_NONBLOCK); +- } else { +- prepareFile(pData, pData->f_fname); +- } ++ prepareFile(pData, pData->f_fname); + + if ( pData->fd < 0 ){ + pData->fd = -1; +@@ -776,10 +795,6 @@ CODESTARTparseSelectorAct + errmsg.LogError(0, NO_ERRCODE, "%s", pData->f_fname); + break; + } +- if (isatty(pData->fd)) { +- pData->fileType = eTypeTTY; +- untty(); +- } + if (strcmp((char*) p, _PATH_CONSOLE) == 0) + pData->fileType = eTypeCONSOLE; + break; +@@ -815,6 +830,20 @@ static rsRetVal resetConfigVariables(uchar __attribute__((unused)) *pp, void __a + } + + ++BEGINdoHUP ++CODESTARTdoHUP ++ if(pData->bDynamicName) { ++ dynaFileFreeCacheEntries(pData); ++ pData->iCurrElt = -1; /* invalidate current element */ ++ } else { ++ if(pData->fd != -1) { ++ close(pData->fd); ++ pData->fd = -1; ++ } ++ } ++ENDdoHUP ++ ++ + BEGINmodExit + CODESTARTmodExit + if(pszTplName != NULL) +@@ -825,6 +854,7 @@ ENDmodExit + BEGINqueryEtryPt + CODESTARTqueryEtryPt + CODEqueryEtryPt_STD_OMOD_QUERIES ++CODEqueryEtryPt_doHUP + ENDqueryEtryPt + + +diff --git a/tools/syslogd.c b/tools/syslogd.c +index b0d6fa2..98c7882 100644 +--- a/tools/syslogd.c ++++ b/tools/syslogd.c +@@ -219,7 +219,7 @@ static char *PidFile = _PATH_LOGPID; /* read-only after startup */ + + static pid_t myPid; /* our pid for use in self-generated messages, e.g. on startup */ + /* mypid is read-only after the initial fork() */ +-static int restart = 0; /* do restart (config read) - multithread safe */ ++static int bHadHUP = 0; /* did we have a HUP? */ + + static int bParseHOSTNAMEandTAG = 1; /* global config var: should the hostname and tag be + * parsed inside message - rgerhards, 2006-03-13 */ +@@ -2525,13 +2525,13 @@ static rsRetVal setMainMsgQueType(void __attribute__((unused)) *pVal, uchar *psz + * The following function is resposible for handling a SIGHUP signal. Since + * we are now doing mallocs/free as part of init we had better not being + * doing this during a signal handler. Instead this function simply sets +- * a flag variable which will tell the main loop to go through a restart. ++ * a flag variable which will tells the main loop to do "the right thing". + */ + void sighup_handler() + { + struct sigaction sigAct; + +- restart = 1; ++ bHadHUP = 1; + + memset(&sigAct, 0, sizeof (sigAct)); + sigemptyset(&sigAct.sa_mask); +@@ -2560,6 +2560,49 @@ static void processImInternal(void) + } + + ++/* helper to doHUP(), this "HUPs" each action. The necessary locking ++ * is done inside the action class and nothing we need to take care of. ++ * rgerhards, 2008-10-22 ++ */ ++DEFFUNC_llExecFunc(doHUPActions) ++{ ++ BEGINfunc ++ actionCallHUPHdlr((action_t*) pData); ++ ENDfunc ++ return RS_RET_OK; /* we ignore errors, we can not do anything either way */ ++} ++ ++ ++/* This function processes a HUP after one has been detected. Note that this ++ * is *NOT* the sighup handler. The signal is recorded by the handler, that record ++ * detected inside the mainloop and then this function is called to do the ++ * real work. -- rgerhards, 2008-10-22 ++ */ ++static inline void ++doHUP(void) ++{ ++ selector_t *f; ++ char buf[512]; ++ ++ snprintf(buf, sizeof(buf) / sizeof(char), ++ " [origin software=\"rsyslogd\" " "swVersion=\"" VERSION ++ "\" x-pid=\"%d\" x-info=\"http://www.rsyslog.com\"] rsyslogd was HUPed, type '%s'.", ++ (int) myPid, glbl.GetHUPisRestart() ? "restart" : "lightweight"); ++ errno = 0; ++ logmsgInternal(NO_ERRCODE, LOG_SYSLOG|LOG_INFO, (uchar*)buf, 0); ++ ++ if(glbl.GetHUPisRestart()) { ++ dbgprintf("Received SIGHUP, configured to be restart, reloading rsyslogd.\n"); ++ init(); /* main queue is stopped as part of init() */ ++ } else { ++ dbgprintf("Received SIGHUP, configured to be a non-restart type of HUP - notifying actions.\n"); ++ for(f = Files; f != NULL ; f = f->f_next) { ++ llExecFunc(&f->llActList, doHUPActions, NULL); ++ } ++ } ++} ++ ++ + /* This is the main processing loop. It is called after successful initialization. + * When it returns, the syslogd terminates. + * Its sole function is to provide some housekeeping things. The real work is done +@@ -2616,11 +2659,9 @@ mainloop(void) + if(bReduceRepeatMsgs == 1) + doFlushRptdMsgs(); + +- if(restart) { +- dbgprintf("\nReceived SIGHUP, reloading rsyslogd.\n"); +- /* main queue is stopped as part of init() */ +- init(); +- restart = 0; ++ if(bHadHUP) { ++ doHUP(); ++ bHadHUP = 0; + continue; + } + } +-- +1.5.5.6 + diff --git a/rsyslog.spec b/rsyslog.spec index 8587e5f..3277474 100644 --- a/rsyslog.spec +++ b/rsyslog.spec @@ -3,7 +3,7 @@ Summary: Enhanced system logging and kernel message trapping daemons Name: rsyslog Version: 3.21.10 -Release: 3%{?dist} +Release: 4%{?dist} License: GPLv3+ Group: System Environment/Daemons URL: http://www.rsyslog.com/ @@ -13,6 +13,7 @@ Source2: rsyslog.conf Source3: rsyslog.sysconfig Source4: rsyslog.log Patch0: rsyslog-3.21.10-convVar.patch +Patch1: rsyslog-3.21.10-HUPisRestart.patch BuildRequires: zlib-devel BuildRequires: autoconf automake Requires: logrotate >= 3.5.2 @@ -89,6 +90,7 @@ IETF standard protocol. %prep %setup -q %patch0 -p1 -b .convVar +%patch1 -p1 -b .HUPisRestart %build export CFLAGS="$RPM_OPT_FLAGS -DSYSLOGD_PIDNAME=\\\"syslogd.pid\\\"" @@ -194,6 +196,9 @@ fi %{_libdir}/rsyslog/lmnsd_gtls.so %changelog +* Tue Mar 31 2009 Lubomir Rintel 3.21.10-4 +- Backport HUPisRestart option + * Wed Mar 18 2009 Tomas Heinrich 3.21.10-3 - fix variables' type conversion in expression-based filters (#485937)