diff --git a/src/ioc/db/callback.c b/src/ioc/db/callback.c index b15220469..903ca3f43 100644 --- a/src/ioc/db/callback.c +++ b/src/ioc/db/callback.c @@ -81,6 +81,10 @@ static int callbackIsInit; static char *threadNamePrefix[NUM_CALLBACK_PRIORITIES] = { "cbLow", "cbMedium", "cbHigh" }; +#define FULL_MSG(name) "callbackRequest: " name " ring buffer full\n" +static char *fullMessage[NUM_CALLBACK_PRIORITIES] = { + FULL_MSG("cbLow"), FULL_MSG("cbMedium"), FULL_MSG("cbHigh") +}; static unsigned int threadPriority[NUM_CALLBACK_PRIORITIES] = { epicsThreadPriorityScanLow - 1, epicsThreadPriorityScanLow + 4, @@ -284,11 +288,7 @@ int callbackRequest(CALLBACK *pcallback) pushOK = epicsRingPointerPush(mySet->queue, pcallback); if (!pushOK) { - char msg[48] = "callbackRequest: "; - - strcat(msg, threadNamePrefix[priority]); - strcat(msg, " ring buffer full\n"); - epicsInterruptContextMessage(msg); + epicsInterruptContextMessage(fullMessage[priority]); mySet->queueOverflow = TRUE; return S_db_bufFull; } diff --git a/src/ioc/misc/dbCore.dbd b/src/ioc/misc/dbCore.dbd index a2ce45806..9d5ae9474 100644 --- a/src/ioc/misc/dbCore.dbd +++ b/src/ioc/misc/dbCore.dbd @@ -9,6 +9,9 @@ variable(atExitDebug,int) # Access security subroutines variable(asCaDebug,int) +# CA server debug flag (very verbose) range[0,5] +variable(CASDEBUG,int) + # Static database access variables variable(dbRecordsOnceOnly,int) variable(dbRecordsAbcSorted,int) diff --git a/src/ioc/rsrv/camessage.c b/src/ioc/rsrv/camessage.c index 49e2acb86..3c01ff12b 100644 --- a/src/ioc/rsrv/camessage.c +++ b/src/ioc/rsrv/camessage.c @@ -226,10 +226,10 @@ va_list args /* * add their context string into the protocol */ - localStatus = epicsVsnprintf ( pMsgString, maxDiagLen, pformat, args ); + localStatus = epicsVsnprintf ( pMsgString, maxDiagLen - size, pformat, args ); if ( localStatus >= 1 ) { unsigned diagLen = ( unsigned ) localStatus; - if ( diagLen < maxDiagLen ) { + if ( diagLen < maxDiagLen - size ) { size += (ca_uint32_t) (diagLen + 1u); } else { @@ -237,7 +237,7 @@ va_list args "caserver: vsend_err: epicsVsnprintf detected " "error message truncation, pFormat = \"%s\"\n", pformat ); - size += maxDiagLen; + size = maxDiagLen; pMsgString [ maxDiagLen - 1 ] = '\0'; } } @@ -2574,8 +2574,10 @@ int camessage ( struct client *client ) * aligned payloads */ if ( msgsize & 0x7 ) { + SEND_LOCK(client); send_err ( &msg, ECA_INTERNAL, client, "CAS: Missaligned protocol rejected" ); + SEND_UNLOCK(client); log_header ( "CAS: Missaligned protocol rejected", client, &msg, 0, nmsg ); status = RSRV_ERROR; @@ -2591,9 +2593,11 @@ int camessage ( struct client *client ) if ( msgsize > client->recv.maxstk ) { casExpandRecvBuffer ( client, msgsize ); if ( msgsize > client->recv.maxstk ) { + SEND_LOCK(client); send_err ( &msg, ECA_TOLARGE, client, "CAS: Server unable to load large request message. Max bytes=%lu", rsrvSizeofLargeBufTCP ); + SEND_UNLOCK(client); log_header ( "CAS: server unable to load large request message", client, &msg, 0, nmsg ); assert ( client->recv.cnt <= client->recv.maxstk ); diff --git a/src/ioc/rsrv/camsgtask.c b/src/ioc/rsrv/camsgtask.c index 65d37c9a9..e2a0d3e18 100644 --- a/src/ioc/rsrv/camsgtask.c +++ b/src/ioc/rsrv/camsgtask.c @@ -42,30 +42,18 @@ void camsgtask ( void *pParm ) { struct client *client = (struct client *) pParm; - osiSockIoctl_t nchars; - int status; casAttachThreadToClient ( client ); - /* - * send the server's minor version number to the client - */ - status = cas_copy_in_header ( client, CA_PROTO_VERSION, 0, - 0, CA_MINOR_PROTOCOL_REVISION, 0, 0, 0 ); - if ( status != ECA_NORMAL ) { - LOCK_CLIENTQ; - ellDelete ( &clientQ, &client->node ); - UNLOCK_CLIENTQ; - destroy_tcp_client ( client ); - return; - } - while (castcp_ctl == ctlRun && !client->disconnect) { + osiSockIoctl_t check_nchars; + long nchars; + int status; /* * allow message to batch up if more are comming */ - status = socket_ioctl (client->sock, FIONREAD, &nchars); + status = socket_ioctl (client->sock, FIONREAD, &check_nchars); if (status < 0) { char sockErrBuf[64]; @@ -75,7 +63,7 @@ void camsgtask ( void *pParm ) sockErrBuf); cas_send_bs_msg(client, TRUE); } - else if (nchars == 0){ + else if (check_nchars == 0){ cas_send_bs_msg(client, TRUE); } @@ -151,6 +139,9 @@ void camsgtask ( void *pParm ) } else { char buf[64]; + + /* flush any queued messages before shutdown */ + cas_send_bs_msg(client, 1); client->recv.cnt = 0ul; diff --git a/src/ioc/rsrv/caserverio.c b/src/ioc/rsrv/caserverio.c index 15a26375a..7250ae6db 100644 --- a/src/ioc/rsrv/caserverio.c +++ b/src/ioc/rsrv/caserverio.c @@ -37,11 +37,18 @@ * cas_send_bs_msg() * * (channel access server send message) + * + * + * Set lock_needed=1 unless SEND_LOCK() is held by caller */ void cas_send_bs_msg ( struct client *pclient, int lock_needed ) { int status; + if ( lock_needed ) { + SEND_LOCK ( pclient ); + } + if ( CASDEBUG > 2 && pclient->send.stk ) { errlogPrintf ( "CAS: Sending a message of %d bytes\n", pclient->send.stk ); } @@ -52,13 +59,11 @@ void cas_send_bs_msg ( struct client *pclient, int lock_needed ) pclient->sock, (unsigned) pclient->addr.sin_addr.s_addr ); } pclient->send.stk = 0u; + if(lock_needed) + SEND_UNLOCK(pclient); return; } - if ( lock_needed ) { - SEND_LOCK ( pclient ); - } - while ( pclient->send.stk && ! pclient->disconnect ) { status = send ( pclient->sock, pclient->send.buf, pclient->send.stk, 0 ); if ( status >= 0 ) { diff --git a/src/ioc/rsrv/rsrvIocRegister.c b/src/ioc/rsrv/rsrvIocRegister.c index 7a01fc9f6..ccbd792dc 100644 --- a/src/ioc/rsrv/rsrvIocRegister.c +++ b/src/ioc/rsrv/rsrvIocRegister.c @@ -7,12 +7,16 @@ * in file LICENSE that is included with this distribution. \*************************************************************************/ +#include "osiSock.h" #include "iocsh.h" #define epicsExportSharedSymbols #include "rsrv.h" +#include "server.h" #include "rsrvIocRegister.h" +#include "epicsExport.h" + /* casr */ static const iocshArg casrArg0 = { "level",iocshArgInt}; static const iocshArg * const casrArgs[1] = {&casrArg0}; @@ -22,8 +26,9 @@ static void casrCallFunc(const iocshArgBuf *args) casr(args[0].ival); } - void rsrvIocRegister(void) { iocshRegister(&casrFuncDef,casrCallFunc); } + +epicsExportAddress(int, CASDEBUG); diff --git a/src/ioc/rsrv/server.h b/src/ioc/rsrv/server.h index 7ace5ad7c..ef9730ba8 100644 --- a/src/ioc/rsrv/server.h +++ b/src/ioc/rsrv/server.h @@ -63,8 +63,10 @@ typedef struct caHdrLargeArray { enum messageBufferType { mbtUDP, mbtSmallTCP, mbtLargeTCP }; struct message_buffer { char *buf; + /*! points to first filled byte in buffer */ unsigned stk; unsigned maxstk; + /*! points to first unused byte in buffer (after filled bytes) */ unsigned cnt; enum messageBufferType type; }; @@ -73,7 +75,9 @@ extern epicsThreadPrivateId rsrvCurrentClient; typedef struct client { ELLNODE node; + /*! guarded by SEND_LOCK() aka. client::lock */ struct message_buffer send; + /*! accessed by receive thread w/o locks cf. camsgtask() */ struct message_buffer recv; epicsMutexId lock; epicsMutexId putNotifyLock;