Cleanup. Handle re-initialization during shutdown gracefully.
This commit is contained in:
+195
-200
@@ -1,17 +1,15 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/*
|
||||
* Author: Marty Kraimer
|
||||
* Original Author: Marty Kraimer
|
||||
* Date: 07JAN1998
|
||||
* NOTE: Original version is adaptation of old version of errPrintfVX.c
|
||||
*/
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
@@ -28,51 +26,45 @@
|
||||
#include "epicsMutex.h"
|
||||
#include "epicsEvent.h"
|
||||
#include "epicsInterrupt.h"
|
||||
#include "epicsAssert.h"
|
||||
#include "errMdef.h"
|
||||
#include "error.h"
|
||||
#include "ellLib.h"
|
||||
#include "errlog.h"
|
||||
#include "logClient.h"
|
||||
#include "epicsStdio.h"
|
||||
#include "epicsExit.h"
|
||||
|
||||
|
||||
#ifndef LOCAL
|
||||
#define LOCAL static
|
||||
#endif /* LOCAL */
|
||||
|
||||
#define BUFFER_SIZE 1280
|
||||
#define MAX_MESSAGE_SIZE 256
|
||||
#define MAX_ALIGNMENT 8
|
||||
|
||||
/*Declare storage for errVerbose */
|
||||
epicsShareDef int errVerbose=0;
|
||||
epicsShareDef int errVerbose = 0;
|
||||
|
||||
LOCAL void errlogCleanup(void);
|
||||
LOCAL void exitHandler(void*);
|
||||
LOCAL void errlogThread(void);
|
||||
static void errlogCleanup(void);
|
||||
static void exitHandler(void *);
|
||||
static void errlogThread(void);
|
||||
|
||||
LOCAL char *msgbufGetFree(int noConsoleMessage);
|
||||
LOCAL void msgbufSetSize(int size); /* Send 'size' chars plus trailing '\0' */
|
||||
LOCAL char * msgbufGetSend(int *noConsoleMessage);
|
||||
LOCAL void msgbufFreeSend(void);
|
||||
static char *msgbufGetFree(int noConsoleMessage);
|
||||
static void msgbufSetSize(int size); /* Send 'size' chars plus trailing '\0' */
|
||||
static char *msgbufGetSend(int *noConsoleMessage);
|
||||
static void msgbufFreeSend(void);
|
||||
|
||||
typedef struct listenerNode{
|
||||
ELLNODE node;
|
||||
ELLNODE node;
|
||||
errlogListener listener;
|
||||
void *pPrivate;
|
||||
}listenerNode;
|
||||
} listenerNode;
|
||||
|
||||
/*each message consists of a msgNode immediately followed by the message */
|
||||
typedef struct msgNode {
|
||||
ELLNODE node;
|
||||
char *message;
|
||||
int length;
|
||||
int noConsoleMessage;
|
||||
ELLNODE node;
|
||||
char *message;
|
||||
int length;
|
||||
int noConsoleMessage;
|
||||
} msgNode;
|
||||
|
||||
LOCAL struct {
|
||||
static struct {
|
||||
epicsEventId waitForWork; /*errlogThread waits for this*/
|
||||
epicsMutexId msgQueueLock;
|
||||
epicsMutexId listenerLock;
|
||||
@@ -91,48 +83,47 @@ LOCAL struct {
|
||||
int toConsole;
|
||||
int missedMessages;
|
||||
void *pbuffer;
|
||||
}pvtData;
|
||||
} pvtData;
|
||||
|
||||
|
||||
/*
|
||||
* vsnprintf with truncation message
|
||||
*/
|
||||
LOCAL int tvsnPrint(char *str, size_t size, const char *format, va_list ap)
|
||||
static int tvsnPrint(char *str, size_t size, const char *format, va_list ap)
|
||||
{
|
||||
int nchar;
|
||||
static const char tmsg[] = "<<TRUNCATED>>\n";
|
||||
int nchar = epicsVsnprintf(str, size, format ? format : "", ap);
|
||||
|
||||
nchar = epicsVsnprintf(str, size, format?format:"", ap);
|
||||
if(nchar >= size) {
|
||||
if (nchar >= size) {
|
||||
if (size > sizeof tmsg)
|
||||
strcpy(str+size-sizeof tmsg, tmsg);
|
||||
strcpy(str + size - sizeof tmsg, tmsg);
|
||||
nchar = size - 1;
|
||||
}
|
||||
return nchar;
|
||||
}
|
||||
|
||||
epicsShareFunc int errlogPrintf( const char *pFormat, ...)
|
||||
epicsShareFunc int errlogPrintf(const char *pFormat, ...)
|
||||
{
|
||||
va_list pvar;
|
||||
int nchar;
|
||||
va_list pvar;
|
||||
int nchar;
|
||||
int isOkToBlock;
|
||||
|
||||
if(epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
if (epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
("errlogPrintf called from interrupt level\n");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
isOkToBlock = epicsThreadIsOkToBlock();
|
||||
errlogInit(0);
|
||||
if(pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
|
||||
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
|
||||
va_start(pvar, pFormat);
|
||||
vfprintf(stderr,pFormat,pvar);
|
||||
vfprintf(stderr, pFormat, pvar);
|
||||
va_end (pvar);
|
||||
fflush(stderr);
|
||||
}
|
||||
va_start(pvar, pFormat);
|
||||
nchar = errlogVprintf(pFormat,pvar);
|
||||
va_end (pvar);
|
||||
nchar = errlogVprintf(pFormat, pvar);
|
||||
va_end(pvar);
|
||||
return(nchar);
|
||||
}
|
||||
|
||||
@@ -143,16 +134,16 @@ epicsShareFunc int errlogVprintf(
|
||||
char *pbuffer;
|
||||
int isOkToBlock;
|
||||
|
||||
if(epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
if (epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
("errlogVprintf called from interrupt level\n");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
errlogInit(0);
|
||||
if(pvtData.atExit) return 0;
|
||||
if (pvtData.atExit) return 0;
|
||||
isOkToBlock = epicsThreadIsOkToBlock();
|
||||
pbuffer = msgbufGetFree(isOkToBlock);
|
||||
if(!pbuffer) return(0);
|
||||
if (!pbuffer) return 0;
|
||||
nchar = tvsnPrint(pbuffer,pvtData.maxMsgSize,pFormat?pFormat:"",pvar);
|
||||
msgbufSetSize(nchar);
|
||||
return nchar;
|
||||
@@ -166,19 +157,19 @@ epicsShareFunc int epicsShareAPI errlogMessage(const char *message)
|
||||
|
||||
epicsShareFunc int errlogPrintfNoConsole( const char *pFormat, ...)
|
||||
{
|
||||
va_list pvar;
|
||||
int nchar;
|
||||
va_list pvar;
|
||||
int nchar;
|
||||
|
||||
if(epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
("errlogPrintf called from interrupt level\n");
|
||||
return 0;
|
||||
if (epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
("errlogPrintfNoConsole called from interrupt level\n");
|
||||
return 0;
|
||||
}
|
||||
errlogInit(0);
|
||||
va_start(pvar, pFormat);
|
||||
nchar = errlogVprintfNoConsole(pFormat,pvar);
|
||||
va_end (pvar);
|
||||
return(nchar);
|
||||
nchar = errlogVprintfNoConsole(pFormat, pvar);
|
||||
va_end(pvar);
|
||||
return nchar;
|
||||
}
|
||||
|
||||
epicsShareFunc int errlogVprintfNoConsole(
|
||||
@@ -187,16 +178,16 @@ epicsShareFunc int errlogVprintfNoConsole(
|
||||
int nchar;
|
||||
char *pbuffer;
|
||||
|
||||
if(epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
("errlogVprintf called from interrupt level\n");
|
||||
return 0;
|
||||
if (epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
("errlogVprintfNoConsole called from interrupt level\n");
|
||||
return 0;
|
||||
}
|
||||
errlogInit(0);
|
||||
if(pvtData.atExit) return 0;
|
||||
if (pvtData.atExit) return 0;
|
||||
pbuffer = msgbufGetFree(1);
|
||||
if(!pbuffer) return(0);
|
||||
nchar = tvsnPrint(pbuffer,pvtData.maxMsgSize,pFormat?pFormat:"",pvar);
|
||||
if (!pbuffer) return 0;
|
||||
nchar = tvsnPrint(pbuffer, pvtData.maxMsgSize, pFormat?pFormat:"", pvar);
|
||||
msgbufSetSize(nchar);
|
||||
return nchar;
|
||||
}
|
||||
@@ -204,59 +195,59 @@ epicsShareFunc int errlogVprintfNoConsole(
|
||||
epicsShareFunc int errlogSevPrintf(
|
||||
const errlogSevEnum severity,const char *pFormat, ...)
|
||||
{
|
||||
va_list pvar;
|
||||
int nchar;
|
||||
int isOkToBlock;
|
||||
va_list pvar;
|
||||
int nchar;
|
||||
int isOkToBlock;
|
||||
|
||||
if(epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
if (epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
("errlogSevPrintf called from interrupt level\n");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
errlogInit(0);
|
||||
if(pvtData.sevToLog>severity) return(0);
|
||||
if (pvtData.sevToLog>severity) return 0;
|
||||
isOkToBlock = epicsThreadIsOkToBlock();
|
||||
if(pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
|
||||
fprintf(stderr,"sevr=%s ",errlogGetSevEnumString(severity));
|
||||
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
|
||||
fprintf(stderr, "sevr=%s ", errlogGetSevEnumString(severity));
|
||||
va_start(pvar, pFormat);
|
||||
vfprintf(stderr,pFormat,pvar);
|
||||
va_end (pvar);
|
||||
vfprintf(stderr, pFormat, pvar);
|
||||
va_end(pvar);
|
||||
fflush(stderr);
|
||||
}
|
||||
va_start(pvar, pFormat);
|
||||
nchar = errlogSevVprintf(severity,pFormat,pvar);
|
||||
va_end (pvar);
|
||||
return(nchar);
|
||||
nchar = errlogSevVprintf(severity, pFormat, pvar);
|
||||
va_end(pvar);
|
||||
return nchar;
|
||||
}
|
||||
|
||||
epicsShareFunc int errlogSevVprintf(
|
||||
const errlogSevEnum severity,const char *pFormat,va_list pvar)
|
||||
{
|
||||
char *pnext;
|
||||
int nchar;
|
||||
int totalChar=0;
|
||||
int isOkToBlock;
|
||||
int nchar;
|
||||
int totalChar = 0;
|
||||
int isOkToBlock;
|
||||
|
||||
if(epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
if (epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage
|
||||
("errlogSevVprintf called from interrupt level\n");
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
errlogInit(0);
|
||||
if(pvtData.atExit) return 0;
|
||||
if (pvtData.atExit) return 0;
|
||||
isOkToBlock = epicsThreadIsOkToBlock();
|
||||
pnext = msgbufGetFree(isOkToBlock);
|
||||
if(!pnext) return(0);
|
||||
nchar = sprintf(pnext,"sevr=%s ",errlogGetSevEnumString(severity));
|
||||
if (!pnext) return 0;
|
||||
nchar = sprintf(pnext, "sevr=%s ", errlogGetSevEnumString(severity));
|
||||
pnext += nchar; totalChar += nchar;
|
||||
nchar = tvsnPrint(pnext,pvtData.maxMsgSize-totalChar-1,pFormat,pvar);
|
||||
nchar = tvsnPrint(pnext, pvtData.maxMsgSize - totalChar - 1, pFormat, pvar);
|
||||
pnext += nchar; totalChar += nchar;
|
||||
if(pnext[-1] != '\n') {
|
||||
if (pnext[-1] != '\n') {
|
||||
strcpy(pnext,"\n");
|
||||
totalChar++;
|
||||
}
|
||||
msgbufSetSize(totalChar);
|
||||
return(nchar);
|
||||
return nchar;
|
||||
}
|
||||
|
||||
epicsShareFunc char * epicsShareAPI errlogGetSevEnumString(
|
||||
@@ -265,12 +256,12 @@ epicsShareFunc char * epicsShareAPI errlogGetSevEnumString(
|
||||
static char unknown[] = "unknown";
|
||||
|
||||
errlogInit(0);
|
||||
if(severity<0 || severity>3) return(unknown);
|
||||
return(errlogSevEnumString[severity]);
|
||||
if (severity < 0 || severity > 3) return unknown;
|
||||
return errlogSevEnumString[severity];
|
||||
}
|
||||
|
||||
epicsShareFunc void epicsShareAPI errlogSetSevToLog(
|
||||
const errlogSevEnum severity )
|
||||
const errlogSevEnum severity)
|
||||
{
|
||||
errlogInit(0);
|
||||
pvtData.sevToLog = severity;
|
||||
@@ -279,7 +270,7 @@ epicsShareFunc void epicsShareAPI errlogSetSevToLog(
|
||||
epicsShareFunc errlogSevEnum epicsShareAPI errlogGetSevToLog()
|
||||
{
|
||||
errlogInit(0);
|
||||
return(pvtData.sevToLog);
|
||||
return pvtData.sevToLog;
|
||||
}
|
||||
|
||||
epicsShareFunc void epicsShareAPI errlogAddListener(
|
||||
@@ -288,7 +279,7 @@ epicsShareFunc void epicsShareAPI errlogAddListener(
|
||||
listenerNode *plistenerNode;
|
||||
|
||||
errlogInit(0);
|
||||
if(pvtData.atExit) return;
|
||||
if (pvtData.atExit) return;
|
||||
plistenerNode = callocMustSucceed(1,sizeof(listenerNode),
|
||||
"errlogAddListener");
|
||||
epicsMutexMustLock(pvtData.listenerLock);
|
||||
@@ -304,18 +295,18 @@ epicsShareFunc void epicsShareAPI errlogRemoveListener(
|
||||
listenerNode *plistenerNode;
|
||||
|
||||
errlogInit(0);
|
||||
if(!pvtData.atExit) epicsMutexMustLock(pvtData.listenerLock);
|
||||
if (!pvtData.atExit) epicsMutexMustLock(pvtData.listenerLock);
|
||||
plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList);
|
||||
while(plistenerNode) {
|
||||
if(plistenerNode->listener==listener) {
|
||||
ellDelete(&pvtData.listenerList,&plistenerNode->node);
|
||||
free((void *)plistenerNode);
|
||||
break;
|
||||
}
|
||||
plistenerNode = (listenerNode *)ellNext(&plistenerNode->node);
|
||||
while (plistenerNode) {
|
||||
if (plistenerNode->listener==listener) {
|
||||
ellDelete(&pvtData.listenerList, &plistenerNode->node);
|
||||
free((void *)plistenerNode);
|
||||
break;
|
||||
}
|
||||
plistenerNode = (listenerNode *)ellNext(&plistenerNode->node);
|
||||
}
|
||||
if(!pvtData.atExit) epicsMutexUnlock(pvtData.listenerLock);
|
||||
if(!plistenerNode) {
|
||||
if (!pvtData.atExit) epicsMutexUnlock(pvtData.listenerLock);
|
||||
if (!plistenerNode) {
|
||||
fprintf(stderr, "errlogRemoveListener did not find listener\n");
|
||||
}
|
||||
}
|
||||
@@ -324,7 +315,7 @@ epicsShareFunc int epicsShareAPI eltc(int yesno)
|
||||
{
|
||||
errlogInit(0);
|
||||
pvtData.toConsole = yesno;
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
epicsShareFunc void errPrintf(long status, const char *pFileName,
|
||||
@@ -337,50 +328,50 @@ epicsShareFunc void errPrintf(long status, const char *pFileName,
|
||||
int isOkToBlock;
|
||||
char name[256];
|
||||
|
||||
if(epicsInterruptIsInterruptContext()) {
|
||||
if (epicsInterruptIsInterruptContext()) {
|
||||
epicsInterruptContextMessage("errPrintf called from interrupt level\n");
|
||||
return;
|
||||
}
|
||||
errlogInit(0);
|
||||
isOkToBlock = epicsThreadIsOkToBlock();
|
||||
if(status==0) status = errno;
|
||||
if(status>0) {
|
||||
errSymLookup(status,name,sizeof(name));
|
||||
if (status == 0) status = errno;
|
||||
if (status > 0) {
|
||||
errSymLookup(status, name, sizeof(name));
|
||||
}
|
||||
if(pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
|
||||
if(pFileName) fprintf(stderr,
|
||||
"filename=\"%s\" line number=%d\n",pFileName, lineno);
|
||||
if(status>0) fprintf(stderr,"%s ",name);
|
||||
va_start (pvar, pformat);
|
||||
vfprintf(stderr,pformat,pvar);
|
||||
va_end (pvar);
|
||||
if (pvtData.atExit || (isOkToBlock && pvtData.toConsole)) {
|
||||
if (pFileName) fprintf(stderr, "filename=\"%s\" line number=%d\n",
|
||||
pFileName, lineno);
|
||||
if (status>0) fprintf(stderr, "%s ", name);
|
||||
va_start(pvar, pformat);
|
||||
vfprintf(stderr, pformat, pvar);
|
||||
va_end(pvar);
|
||||
fflush(stderr);
|
||||
}
|
||||
if(pvtData.atExit) return;
|
||||
if (pvtData.atExit) return;
|
||||
pnext = msgbufGetFree(isOkToBlock);
|
||||
if(!pnext) return;
|
||||
if(pFileName){
|
||||
if (!pnext) return;
|
||||
if (pFileName) {
|
||||
nchar = sprintf(pnext,"filename=\"%s\" line number=%d\n",
|
||||
pFileName, lineno);
|
||||
pnext += nchar; totalChar += nchar;
|
||||
}
|
||||
if(status>0) {
|
||||
if (status > 0) {
|
||||
nchar = sprintf(pnext,"%s ",name);
|
||||
pnext += nchar; totalChar += nchar;
|
||||
}
|
||||
va_start (pvar, pformat);
|
||||
nchar = tvsnPrint(pnext,pvtData.maxMsgSize,pformat,pvar);
|
||||
va_end (pvar);
|
||||
if(nchar>0) {
|
||||
va_start(pvar, pformat);
|
||||
nchar = tvsnPrint(pnext, pvtData.maxMsgSize, pformat, pvar);
|
||||
va_end(pvar);
|
||||
if (nchar>0) {
|
||||
pnext += nchar;
|
||||
totalChar += nchar;
|
||||
}
|
||||
strcpy(pnext,"\n");
|
||||
strcpy(pnext, "\n");
|
||||
totalChar++ ; /*include the \n */
|
||||
msgbufSetSize(totalChar);
|
||||
}
|
||||
|
||||
LOCAL void exitHandler(void *pvt)
|
||||
static void exitHandler(void *pvt)
|
||||
{
|
||||
pvtData.atExit = 1;
|
||||
epicsEventSignal(pvtData.waitForWork);
|
||||
@@ -394,7 +385,7 @@ struct initArgs {
|
||||
int maxMsgSize;
|
||||
};
|
||||
|
||||
LOCAL void errlogInitPvt(void *arg)
|
||||
static void errlogInitPvt(void *arg)
|
||||
{
|
||||
struct initArgs *pconfig = (struct initArgs *) arg;
|
||||
epicsThreadId tid;
|
||||
@@ -422,7 +413,7 @@ LOCAL void errlogInitPvt(void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
LOCAL void errlogCleanup(void)
|
||||
static void errlogCleanup(void)
|
||||
{
|
||||
free(pvtData.pbuffer);
|
||||
epicsMutexDestroy(pvtData.flushLock);
|
||||
@@ -436,19 +427,22 @@ LOCAL void errlogCleanup(void)
|
||||
|
||||
epicsShareFunc int epicsShareAPI errlogInit2(int bufsize, int maxMsgSize)
|
||||
{
|
||||
static epicsThreadOnceId errlogOnceFlag=EPICS_THREAD_ONCE_INIT;
|
||||
static epicsThreadOnceId errlogOnceFlag = EPICS_THREAD_ONCE_INIT;
|
||||
struct initArgs config;
|
||||
|
||||
if (errlogOnceFlag > 0 && pvtData.atExit)
|
||||
return 0;
|
||||
|
||||
if (bufsize < BUFFER_SIZE) bufsize = BUFFER_SIZE;
|
||||
config.bufsize = bufsize;
|
||||
if (maxMsgSize < MAX_MESSAGE_SIZE) maxMsgSize = MAX_MESSAGE_SIZE;
|
||||
config.maxMsgSize = maxMsgSize;
|
||||
epicsThreadOnce(&errlogOnceFlag, errlogInitPvt, (void *)&config);
|
||||
if(pvtData.errlogInitFailed) {
|
||||
if (pvtData.errlogInitFailed) {
|
||||
fprintf(stderr,"errlogInit failed\n");
|
||||
exit(1);
|
||||
}
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
epicsShareFunc int epicsShareAPI errlogInit(int bufsize)
|
||||
{
|
||||
@@ -458,12 +452,12 @@ epicsShareFunc void epicsShareAPI errlogFlush(void)
|
||||
{
|
||||
int count;
|
||||
errlogInit(0);
|
||||
if(pvtData.atExit) return;
|
||||
if (pvtData.atExit) return;
|
||||
/*If nothing in queue dont wake up errlogThread*/
|
||||
epicsMutexMustLock(pvtData.msgQueueLock);
|
||||
count = ellCount(&pvtData.msgQueue);
|
||||
epicsMutexUnlock(pvtData.msgQueueLock);
|
||||
if(count<=0) return;
|
||||
if (count <= 0) return;
|
||||
/*must let errlogThread empty queue*/
|
||||
epicsMutexMustLock(pvtData.flushLock);
|
||||
epicsEventSignal(pvtData.flush);
|
||||
@@ -472,33 +466,33 @@ epicsShareFunc void epicsShareAPI errlogFlush(void)
|
||||
epicsMutexUnlock(pvtData.flushLock);
|
||||
}
|
||||
|
||||
LOCAL void errlogThread(void)
|
||||
static void errlogThread(void)
|
||||
{
|
||||
listenerNode *plistenerNode;
|
||||
int noConsoleMessage;
|
||||
char *pmessage;
|
||||
int noConsoleMessage;
|
||||
char *pmessage;
|
||||
|
||||
epicsAtExit(exitHandler,0);
|
||||
while(TRUE) {
|
||||
epicsEventMustWait(pvtData.waitForWork);
|
||||
if(pvtData.atExit) break;
|
||||
while((pmessage = msgbufGetSend(&noConsoleMessage))) {
|
||||
if(pvtData.atExit) break;
|
||||
epicsMutexMustLock(pvtData.listenerLock);
|
||||
if(pvtData.toConsole && !noConsoleMessage) {
|
||||
while (TRUE) {
|
||||
epicsEventMustWait(pvtData.waitForWork);
|
||||
if (pvtData.atExit) break;
|
||||
while ((pmessage = msgbufGetSend(&noConsoleMessage))) {
|
||||
if (pvtData.atExit) break;
|
||||
epicsMutexMustLock(pvtData.listenerLock);
|
||||
if (pvtData.toConsole && !noConsoleMessage) {
|
||||
fprintf(stderr,"%s",pmessage);
|
||||
fflush(stderr);
|
||||
}
|
||||
plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList);
|
||||
while(plistenerNode) {
|
||||
(*plistenerNode->listener)(plistenerNode->pPrivate, pmessage);
|
||||
plistenerNode = (listenerNode *)ellNext(&plistenerNode->node);
|
||||
}
|
||||
plistenerNode = (listenerNode *)ellFirst(&pvtData.listenerList);
|
||||
while (plistenerNode) {
|
||||
(*plistenerNode->listener)(plistenerNode->pPrivate, pmessage);
|
||||
plistenerNode = (listenerNode *)ellNext(&plistenerNode->node);
|
||||
}
|
||||
epicsMutexUnlock(pvtData.listenerLock);
|
||||
msgbufFreeSend();
|
||||
}
|
||||
if(pvtData.atExit) break;
|
||||
if(epicsEventTryWait(pvtData.flush)!=epicsEventWaitOK) continue;
|
||||
msgbufFreeSend();
|
||||
}
|
||||
if (pvtData.atExit) break;
|
||||
if (epicsEventTryWait(pvtData.flush) != epicsEventWaitOK) continue;
|
||||
epicsThreadSleep(.2); /*just wait an extra .2 seconds*/
|
||||
epicsEventSignal(pvtData.waitForFlush);
|
||||
}
|
||||
@@ -506,70 +500,71 @@ LOCAL void errlogThread(void)
|
||||
epicsEventSignal(pvtData.waitForExit);
|
||||
}
|
||||
|
||||
LOCAL msgNode *msgbufGetNode()
|
||||
static msgNode *msgbufGetNode()
|
||||
{
|
||||
char *pbuffer = (char *)pvtData.pbuffer;
|
||||
msgNode *pnextSend = 0;
|
||||
char *pbuffer = (char *)pvtData.pbuffer;
|
||||
msgNode *pnextSend = 0;
|
||||
|
||||
if(ellCount(&pvtData.msgQueue) == 0 ) {
|
||||
pnextSend = (msgNode *)pbuffer;
|
||||
if (ellCount(&pvtData.msgQueue) == 0 ) {
|
||||
pnextSend = (msgNode *)pbuffer;
|
||||
} else {
|
||||
int needed;
|
||||
int remaining;
|
||||
msgNode *plast;
|
||||
int needed;
|
||||
int remaining;
|
||||
msgNode *plast;
|
||||
|
||||
plast = (msgNode *)ellLast(&pvtData.msgQueue);
|
||||
needed = pvtData.maxMsgSize + sizeof(msgNode) + MAX_ALIGNMENT;
|
||||
remaining = pvtData.buffersize
|
||||
- ((plast->message - pbuffer) + plast->length);
|
||||
if(needed < remaining) {
|
||||
int length,adjust;
|
||||
plast = (msgNode *)ellLast(&pvtData.msgQueue);
|
||||
needed = pvtData.maxMsgSize + sizeof(msgNode) + MAX_ALIGNMENT;
|
||||
remaining = pvtData.buffersize
|
||||
- ((plast->message - pbuffer) + plast->length);
|
||||
if (needed < remaining) {
|
||||
int length, adjust;
|
||||
|
||||
length = plast->length;
|
||||
/*Make length a multiple of MAX_ALIGNMENT*/
|
||||
adjust = length%MAX_ALIGNMENT;
|
||||
if(adjust) length += (MAX_ALIGNMENT-adjust);
|
||||
pnextSend = (msgNode *)(plast->message + length);
|
||||
}
|
||||
length = plast->length;
|
||||
/*Make length a multiple of MAX_ALIGNMENT*/
|
||||
adjust = length%MAX_ALIGNMENT;
|
||||
if(adjust) length += (MAX_ALIGNMENT-adjust);
|
||||
pnextSend = (msgNode *)(plast->message + length);
|
||||
}
|
||||
}
|
||||
if(!pnextSend) return(0);
|
||||
if (!pnextSend) return 0;
|
||||
pnextSend->message = (char *)pnextSend + sizeof(msgNode);
|
||||
pnextSend->length = 0;
|
||||
return(pnextSend);
|
||||
return pnextSend;
|
||||
}
|
||||
|
||||
LOCAL char *msgbufGetFree(int noConsoleMessage)
|
||||
static char *msgbufGetFree(int noConsoleMessage)
|
||||
{
|
||||
msgNode *pnextSend;
|
||||
msgNode *pnextSend;
|
||||
|
||||
epicsMutexMustLock(pvtData.msgQueueLock);
|
||||
if((ellCount(&pvtData.msgQueue) == 0) && pvtData.missedMessages) {
|
||||
int nchar;
|
||||
if ((ellCount(&pvtData.msgQueue) == 0) && pvtData.missedMessages) {
|
||||
int nchar;
|
||||
|
||||
pnextSend = msgbufGetNode();
|
||||
nchar = sprintf(pnextSend->message,"errlog = %d messages were discarded\n",
|
||||
pvtData.missedMessages);
|
||||
pnextSend->length = nchar + 1;
|
||||
pvtData.missedMessages = 0;
|
||||
ellAdd(&pvtData.msgQueue,&pnextSend->node);
|
||||
pnextSend = msgbufGetNode();
|
||||
nchar = sprintf(pnextSend->message,
|
||||
"errlog = %d messages were discarded\n",
|
||||
pvtData.missedMessages);
|
||||
pnextSend->length = nchar + 1;
|
||||
pvtData.missedMessages = 0;
|
||||
ellAdd(&pvtData.msgQueue, &pnextSend->node);
|
||||
}
|
||||
pvtData.pnextSend = pnextSend = msgbufGetNode();
|
||||
if(pnextSend) {
|
||||
if (pnextSend) {
|
||||
pnextSend->noConsoleMessage = noConsoleMessage;
|
||||
pnextSend->length = 0;
|
||||
return(pnextSend->message);
|
||||
return pnextSend->message;
|
||||
}
|
||||
++pvtData.missedMessages;
|
||||
epicsMutexUnlock(pvtData.msgQueueLock);
|
||||
return(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
LOCAL void msgbufSetSize(int size)
|
||||
static void msgbufSetSize(int size)
|
||||
{
|
||||
msgNode *pnextSend = pvtData.pnextSend;
|
||||
msgNode *pnextSend = pvtData.pnextSend;
|
||||
|
||||
pnextSend->length = size+1;
|
||||
ellAdd(&pvtData.msgQueue,&pnextSend->node);
|
||||
ellAdd(&pvtData.msgQueue, &pnextSend->node);
|
||||
epicsMutexUnlock(pvtData.msgQueueLock);
|
||||
epicsEventSignal(pvtData.waitForWork);
|
||||
}
|
||||
@@ -578,28 +573,28 @@ LOCAL void msgbufSetSize(int size)
|
||||
/*Thus errlogThread is the ONLY task that removes messages from msgQueue */
|
||||
/*This is why each can lock and unlock msgQueue */
|
||||
/*This is necessary to prevent other tasks from waiting for errlogThread */
|
||||
LOCAL char * msgbufGetSend(int *noConsoleMessage)
|
||||
static char * msgbufGetSend(int *noConsoleMessage)
|
||||
{
|
||||
msgNode *pnextSend;
|
||||
msgNode *pnextSend;
|
||||
|
||||
epicsMutexMustLock(pvtData.msgQueueLock);
|
||||
pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue);
|
||||
epicsMutexUnlock(pvtData.msgQueueLock);
|
||||
if(!pnextSend) return(0);
|
||||
if (!pnextSend) return(0);
|
||||
*noConsoleMessage = pnextSend->noConsoleMessage;
|
||||
return(pnextSend->message);
|
||||
}
|
||||
|
||||
LOCAL void msgbufFreeSend()
|
||||
static void msgbufFreeSend()
|
||||
{
|
||||
msgNode *pnextSend;
|
||||
msgNode *pnextSend;
|
||||
|
||||
epicsMutexMustLock(pvtData.msgQueueLock);
|
||||
pnextSend = (msgNode *)ellFirst(&pvtData.msgQueue);
|
||||
if(!pnextSend) {
|
||||
fprintf(stderr, "errlog: msgbufFreeSend logic error\n");
|
||||
epicsThreadSuspendSelf();
|
||||
if (!pnextSend) {
|
||||
fprintf(stderr, "errlog: msgbufFreeSend logic error\n");
|
||||
epicsThreadSuspendSelf();
|
||||
}
|
||||
ellDelete(&pvtData.msgQueue,&pnextSend->node);
|
||||
ellDelete(&pvtData.msgQueue, &pnextSend->node);
|
||||
epicsMutexUnlock(pvtData.msgQueueLock);
|
||||
}
|
||||
|
||||
@@ -1,13 +1,11 @@
|
||||
/*************************************************************************\
|
||||
* Copyright (c) 2002 The University of Chicago, as Operator of Argonne
|
||||
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
|
||||
* National Laboratory.
|
||||
* Copyright (c) 2002 The Regents of the University of California, as
|
||||
* Operator of Los Alamos National Laboratory.
|
||||
* EPICS BASE Versions 3.13.7
|
||||
* and higher are distributed subject to a Software License Agreement found
|
||||
* EPICS BASE is distributed subject to a Software License Agreement found
|
||||
* in file LICENSE that is included with this distribution.
|
||||
\*************************************************************************/
|
||||
/* src/libCom/errlog.h */
|
||||
|
||||
#ifndef INCerrlogh
|
||||
#define INCerrlogh
|
||||
@@ -29,9 +27,9 @@ extern "C" {
|
||||
#define epicsPrintf errlogPrintf
|
||||
#define epicsVprintf errlogVprintf
|
||||
|
||||
typedef void(*errlogListener) (void *pPrivate, const char *message);
|
||||
typedef void (*errlogListener)(void *pPrivate, const char *message);
|
||||
|
||||
typedef enum {errlogInfo,errlogMinor,errlogMajor,errlogFatal} errlogSevEnum;
|
||||
typedef enum {errlogInfo, errlogMinor, errlogMajor, errlogFatal} errlogSevEnum;
|
||||
|
||||
#ifdef ERRLOG_INIT
|
||||
epicsShareDef char * errlogSevEnumString[] = {"info","minor","major","fatal"};
|
||||
|
||||
Reference in New Issue
Block a user