diff --git a/configure/CONFIG_SITE b/configure/CONFIG_SITE index a3749bc06..12a8603af 100644 --- a/configure/CONFIG_SITE +++ b/configure/CONFIG_SITE @@ -191,7 +191,7 @@ USE_POSIX_THREAD_PRIORITY_SCHEDULING = YES # Site version number, if set will append '-' and this string to the # EPICS version number string that is reported by many tools -EPICS_SITE_VERSION := $(shell date +%Y-%m) +EPICS_SITE_VERSION=$(shell $(PERL) -MPOSIX -e 'print strftime "%Y-%m-%d_$(shell git describe --tags --dirty)", localtime') # For GNU compiler, use pipes rather than temporary files for communication # between the various stages of compilation. diff --git a/configure/os/CONFIG.Common.RHEL7-x86_64 b/configure/os/CONFIG.Common.RHEL7-x86_64 index 083caea5f..757bcb323 100644 --- a/configure/os/CONFIG.Common.RHEL7-x86_64 +++ b/configure/os/CONFIG.Common.RHEL7-x86_64 @@ -1,4 +1,2 @@ # Include definitions common to linux pentium targets include $(CONFIG)/os/CONFIG.Common.linux-x86_64 - -COMMANDLINE_LIBRARY = READLINE diff --git a/configure/os/CONFIG.Common.RHEL7-x86_64-clang b/configure/os/CONFIG.Common.RHEL7-x86_64-clang index 57f57aa53..fa50b4f9c 100644 --- a/configure/os/CONFIG.Common.RHEL7-x86_64-clang +++ b/configure/os/CONFIG.Common.RHEL7-x86_64-clang @@ -1,3 +1 @@ include $(CONFIG)/os/CONFIG.Common.linux-clang - -COMMANDLINE_LIBRARY = READLINE diff --git a/configure/os/CONFIG.Common.SL6-x86 b/configure/os/CONFIG.Common.SL6-x86 index e5d9c2804..434c55396 100644 --- a/configure/os/CONFIG.Common.SL6-x86 +++ b/configure/os/CONFIG.Common.SL6-x86 @@ -1,6 +1,4 @@ # Include definitions common to linux pentium targets include $(CONFIG)/os/CONFIG.Common.linux-x86 -COMMANDLINE_LIBRARY = READLINE - ARCH_DEP_CFLAGS += -march=i686 diff --git a/configure/os/CONFIG.Common.SL6-x86_64 b/configure/os/CONFIG.Common.SL6-x86_64 index 083caea5f..757bcb323 100644 --- a/configure/os/CONFIG.Common.SL6-x86_64 +++ b/configure/os/CONFIG.Common.SL6-x86_64 @@ -1,4 +1,2 @@ # Include definitions common to linux pentium targets include $(CONFIG)/os/CONFIG.Common.linux-x86_64 - -COMMANDLINE_LIBRARY = READLINE diff --git a/configure/os/CONFIG.Common.SL6-x86_64-clang b/configure/os/CONFIG.Common.SL6-x86_64-clang index 57f57aa53..fa50b4f9c 100644 --- a/configure/os/CONFIG.Common.SL6-x86_64-clang +++ b/configure/os/CONFIG.Common.SL6-x86_64-clang @@ -1,3 +1 @@ include $(CONFIG)/os/CONFIG.Common.linux-clang - -COMMANDLINE_LIBRARY = READLINE diff --git a/configure/os/CONFIG.Common.T2-ppc604 b/configure/os/CONFIG.Common.T2-ppc604 index 52c0650b5..99deb1567 100644 --- a/configure/os/CONFIG.Common.T2-ppc604 +++ b/configure/os/CONFIG.Common.T2-ppc604 @@ -1,5 +1,5 @@ include $(CONFIG)/os/CONFIG.Common.vxWorks-ppc604_long -VXWORKS_VERSION = 5.5.1 +VXWORKS_VERSION = 5.5 WIND_BASE = /afs/psi.ch/project/vxworks/Tornado2.2.1 #there is a problem with our ccppc and optimization diff --git a/configure/os/CONFIG.Common.eldk51-ppc4xxSF b/configure/os/CONFIG.Common.eldk51-ppc4xxSF index 276e5b99e..48b3e7e3b 100644 --- a/configure/os/CONFIG.Common.eldk51-ppc4xxSF +++ b/configure/os/CONFIG.Common.eldk51-ppc4xxSF @@ -3,8 +3,6 @@ # Include definitions common to all Linux targets include $(CONFIG)/os/CONFIG.Common.linuxCommon -COMMANDLINE_LIBRARY = READLINE - ARCH_CLASS = ppc SDK = eldk diff --git a/configure/os/CONFIG.Common.eldk52-e500v2 b/configure/os/CONFIG.Common.eldk52-e500v2 index fc6e21e9e..ff1d5ffd6 100644 --- a/configure/os/CONFIG.Common.eldk52-e500v2 +++ b/configure/os/CONFIG.Common.eldk52-e500v2 @@ -3,8 +3,6 @@ # Include definitions common to all Linux targets include $(CONFIG)/os/CONFIG.Common.linuxCommon -COMMANDLINE_LIBRARY = READLINE - ARCH_CLASS = ppc SDK = eldk diff --git a/configure/os/CONFIG.Common.eldk53-ppc4xxFP b/configure/os/CONFIG.Common.eldk53-ppc4xxFP new file mode 100644 index 000000000..554b9d918 --- /dev/null +++ b/configure/os/CONFIG.Common.eldk53-ppc4xxFP @@ -0,0 +1,21 @@ +# DeltaTau PowerPMAC with ELDK 5.3 + +# Include definitions common to all Linux targets +include $(CONFIG)/os/CONFIG.Common.linuxCommon + +ARCH_CLASS = ppc + +SDK = eldk +SDK_DIR = /opt/eldk-5.3 +SDK_HOST_ARCH = $(GNU_HOST_ARCH)-$(SDK)-$(GNU_HOST_OS) +GNU_ARCH = ppc440e-linux +SDKTARGETSYSROOT=$(SDK_DIR)/powerpc-4xx/sysroots +GNU_DIR = $(SDKTARGETSYSROOT)/$(SDK_HOST_ARCH)/usr +GNU_BIN = $(GNU_DIR)/bin/$(GNU_ARCH) +GNU_TARGET_INCLUDE_DIR = +GNU_TARGET=powerpc-linux + +ARCH_DEP_CPPFLAGS = -m32 -mcpu=440fp -mhard-float +ARCH_DEP_CPPFLAGS += --sysroot=$(SDKTARGETSYSROOT)/$(GNU_ARCH) +ARCH_DEP_LDFLAGS = --sysroot=$(SDKTARGETSYSROOT)/$(GNU_ARCH) +AS=$(GNU_BIN)/$(GNU_TARGET)-as diff --git a/configure/os/CONFIG.Common.fslqoriq20-e6500_64 b/configure/os/CONFIG.Common.fslqoriq20-e6500_64 index ba173bbd9..1e3ba7e61 100644 --- a/configure/os/CONFIG.Common.fslqoriq20-e6500_64 +++ b/configure/os/CONFIG.Common.fslqoriq20-e6500_64 @@ -3,8 +3,6 @@ # Include definitions common to all Linux targets include $(CONFIG)/os/CONFIG.Common.linuxCommon -COMMANDLINE_LIBRARY = READLINE - ARCH_CLASS = ppc SDK = fslsdk diff --git a/configure/os/CONFIG.Common.raspbian-arm b/configure/os/CONFIG.Common.raspbian-arm index c2f6ca3c4..6c69dcfe7 100644 --- a/configure/os/CONFIG.Common.raspbian-arm +++ b/configure/os/CONFIG.Common.raspbian-arm @@ -8,7 +8,7 @@ include $(CONFIG)/os/CONFIG.Common.linuxCommon # Using readline: # Due to missing/messed up libs in the toolchain, readline needs copies of -# libtinfo.so.5.9 and libreadline.so.6.2 from a Raspbian 7 rootfs +# libtinfo.so.5.9 and libreadline.so.6.2 from a Raspbian 7 rootfs # /lib/arm-linux-gnueabihf/ to the toolchain, e.g. # $(SDK_DIR)/gcc-linaro-arm-linux-gnueabihf-raspbian/arm-linux-gnueabihf/libc/lib/arm-linux-gnueabihf/ # and manually created links libtinfo.so.5 and libreadline.so. @@ -18,8 +18,6 @@ include $(CONFIG)/os/CONFIG.Common.linuxCommon # Also copy /usr/include/readline/ directory from some readline 6 installation # to $(SDK_DIR)/gcc-linaro-arm-linux-gnueabihf-raspbian/arm-linux-gnueabihf/libc/usr/include/ -COMMANDLINE_LIBRARY = READLINE - ARCH_CLASS = arm SDK_DIR = /opt/raspberrypi/arm-bcm2708 diff --git a/configure/os/CONFIG.Common.yocto21-aarch64 b/configure/os/CONFIG.Common.yocto21-aarch64 index ba54c9399..3cc1fe1dc 100644 --- a/configure/os/CONFIG.Common.yocto21-aarch64 +++ b/configure/os/CONFIG.Common.yocto21-aarch64 @@ -3,8 +3,6 @@ # Include definitions common to all Linux targets include $(CONFIG)/os/CONFIG.Common.linuxCommon -COMMANDLINE_LIBRARY = READLINE - ARCH_CLASS = arm64 SDK = petalinux diff --git a/configure/os/CONFIG.win32-x86.win32-x86 b/configure/os/CONFIG.win32-x86.win32-x86 index f5b21cc2e..54a0ec954 100644 --- a/configure/os/CONFIG.win32-x86.win32-x86 +++ b/configure/os/CONFIG.win32-x86.win32-x86 @@ -85,16 +85,20 @@ CPP = cl -nologo -C -E # Configure OS vendor C++ compiler # -# __STDC__=0 gives us both: -# 1) define STDC for code (pretend ANSI conformance) -# 2) set it to 0 to use MS C "extensions" (open for _open etc.) -# because MS uses: if __STDC__ ... disable many nice things -# # -EHsc - generate code for exceptions # -GR - generate code for run time type identification # CCC = cl -EHsc -GR -CODE_CPPFLAGS += -nologo -D__STDC__=0 + +# Other compiler flags, used for CPP, C and C++ +# +# -FC - Show absolute path of source file in diagnostics +# -D__STDC__=0 gives us both: +# 1) define STDC for code (pretend ANSI conformance) +# 2) set it to 0 to use MS C "extensions" (open for _open etc.) +# because MS uses: if __STDC__ ... disable many nice things +# +CODE_CPPFLAGS += -nologo -FC -D__STDC__=0 CODE_CPPFLAGS += -D_CRT_SECURE_NO_DEPRECATE -D_CRT_NONSTDC_NO_DEPRECATE diff --git a/configure/os/CONFIG_SITE.Common.linuxCommon b/configure/os/CONFIG_SITE.Common.linuxCommon new file mode 100644 index 000000000..30cfd903b --- /dev/null +++ b/configure/os/CONFIG_SITE.Common.linuxCommon @@ -0,0 +1 @@ +COMMANDLINE_LIBRARY = READLINE diff --git a/configure/os/CONFIG_SITE.SL6-x86_64.Common b/configure/os/CONFIG_SITE.SL6-x86_64.Common index 9d8cb9f96..7aa041e73 100644 --- a/configure/os/CONFIG_SITE.SL6-x86_64.Common +++ b/configure/os/CONFIG_SITE.SL6-x86_64.Common @@ -2,6 +2,6 @@ CROSS_COMPILER_TARGET_ARCHS += SL6-x86 # Improved error checking with clang -CROSS_COMPILER_TARGET_ARCHS += SL6-x86_64-clang +#CROSS_COMPILER_TARGET_ARCHS += SL6-x86_64-clang include $(CONFIG)/os/CONFIG_SITE.linux-x86_64.Common diff --git a/configure/os/CONFIG_SITE.linux-x86.Common b/configure/os/CONFIG_SITE.linux-x86.Common index fb3b6213d..4baf36444 100644 --- a/configure/os/CONFIG_SITE.linux-x86.Common +++ b/configure/os/CONFIG_SITE.linux-x86.Common @@ -10,6 +10,7 @@ GNU_HOST_ARCH=i686 GNU_HOST_OS=linux +LD_LIBRARY_PATH= # vxWorks 5 for MVxxxx boards CROSS_COMPILER_TARGET_ARCHS += T2-ppc604 @@ -34,6 +35,7 @@ CROSS_COMPILER_TARGET_ARCHS += eldk52-e500v2 # DeltaTau PowerPMAC CROSS_COMPILER_TARGET_ARCHS += eldk42-ppc4xxFP +CROSS_COMPILER_TARGET_ARCHS += eldk53-ppc4xxFP # Test other vxWorks versions CROSS_COMPILER_TARGET_ARCHS += V66-ppc603 diff --git a/src/db/Makefile b/src/db/Makefile index e66e3be4e..abfb56675 100644 --- a/src/db/Makefile +++ b/src/db/Makefile @@ -35,7 +35,6 @@ INC += db_access_routines.h INC += db_convert.h INC += dbCaPvt.h - DBDINC += menuAlarmSevr DBDINC += menuAlarmStat DBDINC += menuCompress diff --git a/src/dbStatic/dbLexRoutines.c b/src/dbStatic/dbLexRoutines.c index db95cc61f..87a286b2c 100644 --- a/src/dbStatic/dbLexRoutines.c +++ b/src/dbStatic/dbLexRoutines.c @@ -47,6 +47,9 @@ epicsExportAddress(int,dbRecordsOnceOnly); epicsShareDef int dbBptNotMonotonic=0; epicsExportAddress(int,dbBptNotMonotonic); +epicsShareDef int dbQuietMacroWarnings=0; +epicsExportAddress(int,dbQuietMacroWarnings); + /*private routines */ static void yyerrorAbort(char *str); static void allocTemp(void *pvoid); @@ -227,6 +230,7 @@ static long dbReadCOM(DBBASE **ppdbbase,const char *filename, FILE *fp, free((void *)macPairs); mac_input_buffer = dbCalloc(MY_BUFFER_SIZE,sizeof(char)); } + macSuppressWarning(macHandle,dbQuietMacroWarnings); } pinputFile = dbCalloc(1,sizeof(inputFile)); if (filename) { @@ -960,23 +964,29 @@ static void dbRecordHead(char *recordType, char *name, int visible) static void dbRecordField(char *name,char *value) { - DBENTRY *pdbentry; - tempListNode *ptempListNode; - long status; + DBENTRY *pdbentry; + tempListNode *ptempListNode; + long status; - if(duplicate) return; + if (duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; status = dbFindField(pdbentry,name); - if(status) { - epicsPrintf("Record \"%s\" does not have a field \"%s\"\n", - dbGetRecordName(pdbentry), name); - yyerror(NULL); - return; + if (status) { + epicsPrintf("Record \"%s\" does not have a field \"%s\"\n", + dbGetRecordName(pdbentry), name); + yyerror(NULL); + return; + } + if (pdbentry->indfield == 0) { + epicsPrintf("Can't set \"NAME\" field of record \"%s\"\n", + dbGetRecordName(pdbentry)); + yyerror(NULL); + return; } dbTranslateEscape(value, value); /* yuck: in-place, but safe */ status = dbPutString(pdbentry,value); - if(status) { + if (status) { epicsPrintf("Can't set \"%s.%s\" to \"%s\"\n", dbGetRecordName(pdbentry), name, value); yyerror(NULL); @@ -986,33 +996,33 @@ static void dbRecordField(char *name,char *value) static void dbRecordInfo(char *name, char *value) { - DBENTRY *pdbentry; - tempListNode *ptempListNode; - long status; + DBENTRY *pdbentry; + tempListNode *ptempListNode; + long status; - if(duplicate) return; + if (duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; status = dbPutInfo(pdbentry,name,value); - if(status) { - epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n", + if (status) { + epicsPrintf("Can't set \"%s\" info \"%s\" to \"%s\"\n", dbGetRecordName(pdbentry), name, value); - yyerror(NULL); - return; + yyerror(NULL); + return; } } static void dbRecordAlias(char *name) { - DBENTRY *pdbentry; - tempListNode *ptempListNode; - long status; + DBENTRY *pdbentry; + tempListNode *ptempListNode; + long status; - if(duplicate) return; + if (duplicate) return; ptempListNode = (tempListNode *)ellFirst(&tempList); pdbentry = ptempListNode->item; status = dbCreateAlias(pdbentry, name); - if(status) { + if (status) { epicsPrintf("Can't create alias \"%s\" for \"%s\"\n", name, dbGetRecordName(pdbentry)); yyerror(NULL); @@ -1022,15 +1032,16 @@ static void dbRecordAlias(char *name) static void dbAlias(char *name, char *alias) { - DBENTRY dbEntry; - DBENTRY *pdbEntry = &dbEntry; + DBENTRY dbEntry; + DBENTRY *pdbEntry = &dbEntry; dbInitEntry(pdbbase, pdbEntry); if (dbFindRecord(pdbEntry, name)) { epicsPrintf("Alias \"%s\" refers to unknown record \"%s\"\n", alias, name); yyerror(NULL); - } else if (dbCreateAlias(pdbEntry, alias)) { + } + else if (dbCreateAlias(pdbEntry, alias)) { epicsPrintf("Can't create alias \"%s\" referring to \"%s\"\n", alias, name); yyerror(NULL); @@ -1040,14 +1051,14 @@ static void dbAlias(char *name, char *alias) static void dbRecordBody(void) { - DBENTRY *pdbentry; + DBENTRY *pdbentry; - if(duplicate) { - duplicate = FALSE; - return; + if (duplicate) { + duplicate = FALSE; + return; } pdbentry = (DBENTRY *)popFirstTemp(); - if(ellCount(&tempList)) - yyerrorAbort("dbRecordBody: tempList not empty"); + if (ellCount(&tempList)) + yyerrorAbort("dbRecordBody: tempList not empty"); dbFreeEntry(pdbentry); } diff --git a/src/libCom/error/errSymLib.c b/src/libCom/error/errSymLib.c index 84c093c9b..9acd280b3 100644 --- a/src/libCom/error/errSymLib.c +++ b/src/libCom/error/errSymLib.c @@ -51,9 +51,8 @@ typedef struct errnumnode { #define NHASH 256 -static ELLLIST errnumlist = ELLLIST_INIT; -static ERRNUMNODE **hashtable; -static int initialized = FALSE; +static ERRNUMNODE **hashtable = NULL; +#define initialized (hashtable!=NULL) extern ERRSYMTAB_ID errSymTbl; /**************************************************************** @@ -67,12 +66,8 @@ extern ERRSYMTAB_ID errSymTbl; int epicsShareAPI errSymBld(void) { ERRSYMBOL *errArray = errSymTbl->symbols; - ERRNUMNODE *perrNumNode = NULL; - ERRNUMNODE *pNextNode = NULL; - ERRNUMNODE **phashnode = NULL; int i; int modnum; - unsigned short hashInd; if(initialized) return(0); hashtable = (ERRNUMNODE**)callocMustSucceed @@ -89,21 +84,6 @@ int epicsShareAPI errSymBld(void) continue; } } - perrNumNode = (ERRNUMNODE *) ellFirst(&errnumlist); - while (perrNumNode) { - /* hash each perrNumNode->errNum */ - hashInd = errhash(perrNumNode->errNum); - phashnode = (ERRNUMNODE**)&hashtable[hashInd]; - pNextNode = (ERRNUMNODE*) *phashnode; - /* search for last node (NULL) of hashnode linked list */ - while (pNextNode) { - phashnode = &pNextNode->hashnode; - pNextNode = *phashnode; - } - *phashnode = perrNumNode; - perrNumNode = (ERRNUMNODE *) ellNext((ELLNODE *) perrNumNode); - } - initialized = TRUE; return(0); } @@ -125,16 +105,33 @@ unsigned short errnum; /**************************************************************** * ERRSYMBOLADD - * adds symbols to the master errnumlist as compiled from errSymTbl.c + * adds symbols to the master hashtable as compiled from errSymTbl.c ***************************************************************/ int epicsShareAPI errSymbolAdd (long errNum,char *name) { - ERRNUMNODE *pNew; + ERRNUMNODE *perrNumNode; + ERRNUMNODE *pNextNode = NULL; + ERRNUMNODE **phashnode = NULL; + unsigned short hashInd; + + if(!initialized) errSymBld(); + + perrNumNode = (ERRNUMNODE*)callocMustSucceed(1,sizeof(ERRNUMNODE),"errSymbolAdd"); + perrNumNode->errNum = errNum; + perrNumNode->message = name; + + /* hash each perrNumNode->errNum */ + hashInd = errhash(perrNumNode->errNum); + phashnode = (ERRNUMNODE**)&hashtable[hashInd]; + pNextNode = (ERRNUMNODE*) *phashnode; + /* search for last node (NULL) of hashnode linked list */ + while (pNextNode) { + phashnode = &pNextNode->hashnode; + pNextNode = *phashnode; + } + *phashnode = perrNumNode; + perrNumNode = (ERRNUMNODE *) ellNext((ELLNODE *) perrNumNode); - pNew = (ERRNUMNODE*)callocMustSucceed(1,sizeof(ERRNUMNODE),"errSymbolAdd"); - pNew->errNum = errNum; - pNew->message = name; - ellAdd(&errnumlist,(ELLNODE*)pNew); return(0); } diff --git a/src/libCom/logClient/iocLog.c b/src/libCom/logClient/iocLog.c index c6c707c30..d835e3c2c 100644 --- a/src/libCom/logClient/iocLog.c +++ b/src/libCom/logClient/iocLog.c @@ -21,6 +21,7 @@ #include "errlog.h" #include "logClient.h" #include "iocLog.h" +#include "epicsExit.h" int iocLogDisable = 0; @@ -75,6 +76,14 @@ void epicsShareAPI epicsShareAPI iocLogFlush (void) } } +/* + * logClientDestroy() + */ +static void iocLogClientDestroy (logClientId id) +{ + errlogRemoveListener (logClientSendMessage); +} + /* * iocLogClientInit() */ @@ -91,7 +100,8 @@ static logClientId iocLogClientInit (void) } id = logClientCreate (addr, port); if (id != NULL) { - errlogAddListener ( logClientSendMessage, id ); + errlogAddListener (logClientSendMessage, id); + epicsAtExit (iocLogClientDestroy, id); } return id; } @@ -139,13 +149,3 @@ logClientId epicsShareAPI logClientInit (void) { return iocLogClientInit (); } - -/* - * logClientSendMessage (); deprecated - */ -void logClientSendMessage ( logClientId id, const char * message ) -{ - if ( !iocLogDisable ) { - logClientSend (id, message); - } -} diff --git a/src/libCom/logClient/logClient.c b/src/libCom/logClient/logClient.c index 4f5daaab1..f7c9b9ca0 100644 --- a/src/libCom/logClient/logClient.c +++ b/src/libCom/logClient/logClient.c @@ -24,6 +24,7 @@ #define epicsExportSharedSymbols #include "dbDefs.h" #include "epicsEvent.h" +#include "iocLog.h" #include "epicsMutex.h" #include "epicsThread.h" #include "epicsTime.h" @@ -42,6 +43,7 @@ typedef struct { SOCKET sock; epicsThreadId restartThreadId; epicsEventId stateChangeNotify; + epicsEventId shutdownNotify; unsigned connectCount; unsigned nextMsgIndex; unsigned connected; @@ -51,9 +53,13 @@ typedef struct { } logClient; static const double LOG_RESTART_DELAY = 5.0; /* sec */ -static const double LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT = 5.0; /* sec */ static const double LOG_SERVER_SHUTDOWN_TIMEOUT = 30.0; /* sec */ +/* + * If set using iocLogPrefix() this string is prepended to all log messages: + */ +static char* logClientPrefix = NULL; + /* * logClientClose () */ @@ -77,8 +83,6 @@ static void logClientClose ( logClient *pClient ) pClient->sock = INVALID_SOCKET; } - pClient->nextMsgIndex = 0u; - memset ( pClient->msgBuf, '\0', sizeof ( pClient->msgBuf ) ); pClient->connected = 0u; /* @@ -106,6 +110,7 @@ static void logClientDestroy (logClientId id) epicsMutexMustLock ( pClient->mutex ); pClient->shutdown = 1u; epicsMutexUnlock ( pClient->mutex ); + epicsEventSignal ( pClient->shutdownNotify ); /* unblock log client thread blocking in send() or connect() */ interruptInfo = @@ -150,112 +155,109 @@ static void logClientDestroy (logClientId id) logClientClose ( pClient ); epicsMutexDestroy ( pClient->mutex ); - epicsEventDestroy ( pClient->stateChangeNotify ); + epicsEventDestroy ( pClient->shutdownNotify ); free ( pClient ); } +/* + * logClientCheckConnection + */ +static void logClientCheckConnection( logClient * pClient ) +{ + epicsMutexMustLock ( pClient->mutex ); + while ( pClient->connected ) { + struct timeval timeout = { 0, 0 }; + fd_set set; + char buffer[256]; + + FD_ZERO ( &set ); + FD_SET ( pClient->sock, &set ); + if ( select ( pClient->sock + 1, &set, NULL, NULL, &timeout ) == 0) + break; + if ( recv ( pClient->sock, buffer, sizeof ( buffer ), 0 ) == 0 ) { + fprintf ( stderr, "log client: connection closed by server \"%s\"\n", + pClient->name ); + logClientClose ( pClient ); + break; + } + } + epicsMutexUnlock ( pClient->mutex ); +} + +/* + * This method requires the pClient->mutex be owned already. + */ +static void sendMessageChunk(logClient * pClient, const char * message) { + unsigned strSize; + + strSize = strlen ( message ); + while ( strSize ) { + unsigned msgBufBytesLeft = + sizeof ( pClient->msgBuf ) - pClient->nextMsgIndex; + + if ( msgBufBytesLeft < strSize && pClient->nextMsgIndex != 0u && pClient->connected) + { + /* buffer is full, thus flush it */ + logClientCheckConnection( pClient ); + logClientFlush ( pClient ); + msgBufBytesLeft = sizeof ( pClient->msgBuf ) - pClient->nextMsgIndex; + } + if ( msgBufBytesLeft == 0u ) { + fprintf ( stderr, "log client: messages to \"%s\" are lost\n", + pClient->name ); + break; + } + if ( msgBufBytesLeft > strSize) msgBufBytesLeft = strSize; + memcpy ( & pClient->msgBuf[pClient->nextMsgIndex], + message, msgBufBytesLeft ); + pClient->nextMsgIndex += msgBufBytesLeft; + strSize -= msgBufBytesLeft; + message += msgBufBytesLeft; + } +} + + /* * logClientSend () */ void epicsShareAPI logClientSend ( logClientId id, const char * message ) { logClient * pClient = ( logClient * ) id; - unsigned strSize; if ( ! pClient || ! message ) { return; } - strSize = strlen ( message ); - epicsMutexMustLock ( pClient->mutex ); - while ( strSize ) { - unsigned msgBufBytesLeft = - sizeof ( pClient->msgBuf ) - pClient->nextMsgIndex; - - if ( strSize > msgBufBytesLeft ) { - int status; - - if ( ! pClient->connected ) { - break; - } - - if ( msgBufBytesLeft > 0u ) { - memcpy ( & pClient->msgBuf[pClient->nextMsgIndex], - message, msgBufBytesLeft ); - pClient->nextMsgIndex += msgBufBytesLeft; - strSize -= msgBufBytesLeft; - message += msgBufBytesLeft; - } - - status = send ( pClient->sock, pClient->msgBuf, - pClient->nextMsgIndex, 0 ); - if ( status > 0 ) { - unsigned nSent = (unsigned) status; - if ( nSent < pClient->nextMsgIndex ) { - unsigned newNextMsgIndex = pClient->nextMsgIndex - nSent; - memmove ( pClient->msgBuf, & pClient->msgBuf[nSent], - newNextMsgIndex ); - pClient->nextMsgIndex = newNextMsgIndex; - } - else { - pClient->nextMsgIndex = 0u; - } - } - else { - if ( ! pClient->shutdown ) { - char sockErrBuf[64]; - if ( status ) { - epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - } - else { - strcpy ( sockErrBuf, "server initiated disconnect" ); - } - fprintf ( stderr, "log client: lost contact with log server at \"%s\" because \"%s\"\n", - pClient->name, sockErrBuf ); - } - logClientClose ( pClient ); - break; - } - } - else { - memcpy ( & pClient->msgBuf[pClient->nextMsgIndex], - message, strSize ); - pClient->nextMsgIndex += strSize; - break; - } + if (logClientPrefix) { + sendMessageChunk(pClient, logClientPrefix); } - + sendMessageChunk(pClient, message); + epicsMutexUnlock (pClient->mutex); } + void epicsShareAPI logClientFlush ( logClientId id ) { + unsigned nSent = 0u; + logClient * pClient = ( logClient * ) id; - if ( ! pClient ) { + if ( ! pClient || ! pClient->connected ) { return; } epicsMutexMustLock ( pClient->mutex ); - while ( pClient->nextMsgIndex && pClient->connected ) { - int status = send ( pClient->sock, pClient->msgBuf, - pClient->nextMsgIndex, 0 ); + while ( nSent < pClient->nextMsgIndex && pClient->connected ) { + int status = send ( pClient->sock, pClient->msgBuf + nSent, + pClient->nextMsgIndex - nSent, 0 ); if ( status > 0 ) { - unsigned nSent = (unsigned) status; - if ( nSent < pClient->nextMsgIndex ) { - unsigned newNextMsgIndex = pClient->nextMsgIndex - nSent; - memmove ( pClient->msgBuf, & pClient->msgBuf[nSent], - newNextMsgIndex ); - pClient->nextMsgIndex = newNextMsgIndex; - } - else { - pClient->nextMsgIndex = 0u; - } + nSent += (unsigned) status; } else { if ( ! pClient->shutdown ) { @@ -273,6 +275,11 @@ void epicsShareAPI logClientFlush ( logClientId id ) break; } } + pClient->nextMsgIndex -= nSent; + if ( nSent > 0 && pClient->nextMsgIndex > 0 ) { + memmove ( pClient->msgBuf, & pClient->msgBuf[nSent], + pClient->nextMsgIndex ); + } epicsMutexUnlock ( pClient->mutex ); } @@ -377,20 +384,6 @@ static void logClientConnect (logClient *pClient) fprintf (stderr, "log client: unable to enable keepalive option because \"%s\"\n", sockErrBuf); } - /* - * we don't need full-duplex (clients only write), so we shutdown - * the read end of our socket - */ - status = shutdown (pClient->sock, SHUT_RD); - if (status < 0) { - char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( - sockErrBuf, sizeof ( sockErrBuf ) ); - fprintf (stderr, "%s:%d shutdown(%d,SHUT_RD) error was \"%s\"\n", - __FILE__, __LINE__, pClient->sock, sockErrBuf); - /* not fatal (although it shouldn't happen) */ - } - /* * set how long we will wait for the TCP state machine * to clean up when we issue a close(). This @@ -430,20 +423,21 @@ static void logClientRestart ( logClientId id ) /* SMP safe state inspection */ epicsMutexMustLock ( pClient->mutex ); while ( ! pClient->shutdown ) { - unsigned isConn; + unsigned isConn, dataToSend; + + logClientCheckConnection( pClient ); isConn = pClient->connected; + dataToSend = pClient->nextMsgIndex; epicsMutexUnlock ( pClient->mutex ); - if ( isConn ) { + if ( dataToSend ) { + if ( ! isConn ) logClientConnect ( pClient ); logClientFlush ( pClient ); } - else { - logClientConnect ( pClient ); - } - - epicsThreadSleep ( LOG_RESTART_DELAY ); + + epicsEventWaitWithTimeout ( pClient->shutdownNotify, LOG_RESTART_DELAY); epicsMutexMustLock ( pClient->mutex ); } @@ -459,9 +453,7 @@ static void logClientRestart ( logClientId id ) logClientId epicsShareAPI logClientCreate ( struct in_addr server_addr, unsigned short server_port) { - epicsTimeStamp begin, current; logClient *pClient; - double diff; pClient = calloc (1, sizeof (*pClient)); if (pClient==NULL) { @@ -486,14 +478,22 @@ logClientId epicsShareAPI logClientCreate ( pClient->shutdownConfirm = 0; epicsAtExit (logClientDestroy, (void*) pClient); - + pClient->stateChangeNotify = epicsEventCreate (epicsEventEmpty); if ( ! pClient->stateChangeNotify ) { epicsMutexDestroy ( pClient->mutex ); free ( pClient ); return NULL; } - + + pClient->shutdownNotify = epicsEventCreate (epicsEventEmpty); + if ( ! pClient->shutdownNotify ) { + epicsMutexDestroy ( pClient->mutex ); + epicsEventDestroy ( pClient->stateChangeNotify ); + free ( pClient ); + return NULL; + } + pClient->restartThreadId = epicsThreadCreate ( "logRestart", epicsThreadPriorityLow, epicsThreadGetStackSize(epicsThreadStackSmall), @@ -501,33 +501,12 @@ logClientId epicsShareAPI logClientCreate ( if ( pClient->restartThreadId == NULL ) { epicsMutexDestroy ( pClient->mutex ); epicsEventDestroy ( pClient->stateChangeNotify ); + epicsEventDestroy ( pClient->shutdownNotify ); free (pClient); fprintf(stderr, "log client: unable to start log client connection watch dog thread\n"); return NULL; } - /* - * attempt to synchronize with circuit connect - */ - epicsTimeGetCurrent ( & begin ); - epicsMutexMustLock ( pClient->mutex ); - do { - epicsMutexUnlock ( pClient->mutex ); - epicsEventWaitWithTimeout ( - pClient->stateChangeNotify, - LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT / 10.0 ); - epicsTimeGetCurrent ( & current ); - diff = epicsTimeDiffInSeconds ( & current, & begin ); - epicsMutexMustLock ( pClient->mutex ); - } - while ( ! pClient->connected && diff < LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT ); - epicsMutexUnlock ( pClient->mutex ); - - if ( ! pClient->connected ) { - fprintf (stderr, "log client create: timed out synchronizing with circuit connect to \"%s\" after %.1f seconds\n", - pClient->name, LOG_SERVER_CREATE_CONNECT_SYNC_TIMEOUT ); - } - return (void *) pClient; } @@ -537,6 +516,9 @@ logClientId epicsShareAPI logClientCreate ( void epicsShareAPI logClientShow (logClientId id, unsigned level) { logClient *pClient = (logClient *) id; + if ( ! pClient ) { + return; + } if ( pClient->connected ) { printf ("log client: connected to log server at \"%s\"\n", pClient->name); @@ -550,5 +532,46 @@ void epicsShareAPI logClientShow (logClientId id, unsigned level) pClient->sock==INVALID_SOCKET?"INVALID":"OK", pClient->connectCount); } + + if (logClientPrefix) { + printf ("log client: prefix is \"%s\"\n", logClientPrefix); + } } +/* + * logClientSendMessage (); deprecated + */ +void logClientSendMessage ( logClientId id, const char * message ) +{ + if ( !iocLogDisable ) { + logClientSend (id, message); + } +} + +/* + * iocLogPrefix() + */ +void epicsShareAPI iocLogPrefix(const char * prefix) +{ + + /* If we have already established a log prefix, don't let the user change + * it. The iocLogPrefix command is expected to be run from the IOC startup + * script during initialization; the prefix can't be changed once it has + * been set. + */ + + if (logClientPrefix) { + printf ("iocLogPrefix: The prefix was already set to \"%s\" " + "and can't be changed.\n", logClientPrefix); + return; + } + + if (prefix) { + unsigned prefixLen = strlen(prefix); + if (prefixLen > 0) { + char * localCopy = malloc(prefixLen+1); + strcpy(localCopy, prefix); + logClientPrefix = localCopy; + } + } +} diff --git a/src/libCom/logClient/logClient.h b/src/libCom/logClient/logClient.h index 8f1ec09d5..1797bbb20 100644 --- a/src/libCom/logClient/logClient.h +++ b/src/libCom/logClient/logClient.h @@ -33,6 +33,7 @@ epicsShareFunc logClientId epicsShareAPI logClientCreate ( epicsShareFunc void epicsShareAPI logClientSend (logClientId id, const char *message); epicsShareFunc void epicsShareAPI logClientShow (logClientId id, unsigned level); epicsShareFunc void epicsShareAPI logClientFlush (logClientId id); +epicsShareFunc void epicsShareAPI iocLogPrefix(const char* prefix); /* deprecated interface; retained for backward compatibility */ /* note: implementations are in iocLog.c, not logClient.c */ diff --git a/src/misc/base.dbd b/src/misc/base.dbd index 7cecf8c7a..780dad129 100644 --- a/src/misc/base.dbd +++ b/src/misc/base.dbd @@ -49,6 +49,7 @@ variable(CASDEBUG,int) # dbStaticLib settings variable(dbRecordsOnceOnly,int) variable(dbBptNotMonotonic,int) +variable(dbQuietMacroWarnings,int) # dbLoadTemplate settings variable(dbTemplateMaxVars,int) diff --git a/src/rec/seqRecord.c b/src/rec/seqRecord.c index 7627f44e3..9d20726c0 100644 --- a/src/rec/seqRecord.c +++ b/src/rec/seqRecord.c @@ -174,6 +174,7 @@ static long process(seqRecord *prec) linkDesc *plink; unsigned short lmask; int tmp; + int index; if(seqRecDebug > 10) printf("seqRecord: process(%s) pact = %d\n", prec->name, prec->pact); @@ -230,6 +231,7 @@ static long process(seqRecord *prec) } /* Figure out which links are going to be processed */ pcb->index = 0; + index = 0; plink = (linkDesc *)(&(prec->dly1)); tmp = 1; while (lmask) @@ -241,23 +243,21 @@ static long process(seqRecord *prec) if ((lmask & 1) && ((plink->lnk.type != CONSTANT)||(plink->dol.type != CONSTANT))) { if (seqRecDebug > 4) - printf(" seqRec-process Adding link %d at index %d\n", tmp, pcb->index); + printf(" seqRec-process Adding link %d at index %d\n", tmp, index); - pcb->plinks[pcb->index] = plink; - pcb->index++; + pcb->plinks[index++] = plink; } lmask >>= 1; plink++; tmp++; } - pcb->plinks[pcb->index] = NULL; /* mark the bottom of the list */ + pcb->plinks[index] = NULL; /* mark the bottom of the list */ - if (!pcb->index) + if (!index) { /* There was nothing to do, finish record processing here */ return(asyncFinish(prec)); } - pcb->index = 0; /* Start doing the first forward link (We have at least one for sure) */ processNextLink(prec); @@ -367,6 +367,14 @@ static void processCallback(CALLBACK *arg) if (seqRecDebug > 5) printf("processCallback(%s) processing field index %d\n", prec->name, pcb->index+1); + if (pcb->plinks[pcb->index] == NULL) + { + static int overrun = 0; + errlogPrintf("seq record %s: index overrun number %d in callback.\n", prec->name, ++overrun); + dbScanUnlock((struct dbCommon *)prec); + return; + } + /* Save the old value */ myDouble = pcb->plinks[pcb->index]->dov; diff --git a/src/softIoc/Makefile b/src/softIoc/Makefile index 0ddf54187..63d5f5b8a 100644 --- a/src/softIoc/Makefile +++ b/src/softIoc/Makefile @@ -12,6 +12,8 @@ include $(TOP)/configure/CONFIG PROD_IOC_DEFAULT = softIoc PROD_IOC_iOS = -nil- +PROD_LDFLAGS_vxWorks = --whole-archive + DBD += softIoc.dbd softIoc_DBD += base.dbd softIoc_DBD += dlload.dbd