rpms/rsyslog/devel rsyslog-3.21.10-HUPisRestart.patch, NONE, 1.1 rsyslog.spec, 1.57, 1.58

Lubomir Rintel lkundrak at fedoraproject.org
Fri Apr 3 15:01:59 UTC 2009


Author: lkundrak

Update of /cvs/pkgs/rpms/rsyslog/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv32385

Modified Files:
	rsyslog.spec 
Added Files:
	rsyslog-3.21.10-HUPisRestart.patch 
Log Message:
* Tue Mar 31 2009 Lubomir Rintel <lkundrak at v3.sk> 3.21.10-4
- Backport HUPisRestart option


rsyslog-3.21.10-HUPisRestart.patch:

--- NEW FILE rsyslog-3.21.10-HUPisRestart.patch ---
>From 5f83b6a346faca241b310c7d5be2b7eacc6239f9 Mon Sep 17 00:00:00 2001
From: Rainer Gerhards <rgerhards at adiscon.com>
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)]</li>
 <li><a href="rsconf1_gssforwardservicename.html">$GssForwardServiceName</a></li>
 <li><a href="rsconf1_gsslistenservicename.html">$GssListenServiceName</a></li>
 <li><a href="rsconf1_gssmode.html">$GssMode</a></li>
+<li>$HUPisRestart [<b>on</b>/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. <b>It is recommended to set the setting to "off".</b></li>
 <li><a href="rsconf1_includeconfig.html">$IncludeConfig</a></li><li>MainMsgQueueCheckpointInterval &lt;number&gt;</li>
 <li>$MainMsgQueueDequeueSlowdown &lt;number&gt; [number
 is timeout in <i> micro</i>seconds (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



Index: rsyslog.spec
===================================================================
RCS file: /cvs/pkgs/rpms/rsyslog/devel/rsyslog.spec,v
retrieving revision 1.57
retrieving revision 1.58
diff -u -r1.57 -r1.58
--- rsyslog.spec	18 Mar 2009 12:13:41 -0000	1.57
+++ rsyslog.spec	3 Apr 2009 15:01:28 -0000	1.58
@@ -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 @@
 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 @@
 %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 @@
 %{_libdir}/rsyslog/lmnsd_gtls.so
 
 %changelog
+* Tue Mar 31 2009 Lubomir Rintel <lkundrak at v3.sk> 3.21.10-4
+- Backport HUPisRestart option
+
 * Wed Mar 18 2009 Tomas Heinrich <theinric at redhat.com> 3.21.10-3
 - fix variables' type conversion in expression-based filters (#485937)
 




More information about the scm-commits mailing list