From b9ae6c3308f105a2a0b6532616501ae30ff12dc9 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Wed, 18 Jan 2017 10:59:36 -0600 Subject: [PATCH 1/2] Allow ARCH with trailing spaces --- configure/RULES.ioc | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/configure/RULES.ioc b/configure/RULES.ioc index 1024fcb22..4795bc515 100644 --- a/configure/RULES.ioc +++ b/configure/RULES.ioc @@ -14,7 +14,7 @@ build$(DIVIDER)$(ARCH) build: buildInstall install$(DIVIDER)$(ARCH) install: buildInstall $(ARCH): buildInstall -ifeq ($(filter $(ARCH),$(BUILD_ARCHS)),$(ARCH)) +ifeq ($(filter $(ARCH),$(BUILD_ARCHS)),$(strip $(ARCH))) buildInstall$(DIVIDER)$(ARCH) buildInstall: $(TARGETS) clean$(DIVIDER)$(ARCH) clean: @@ -31,4 +31,3 @@ cdCommands envPaths dllPath.bat relPaths.sh: \ realclean: $(RM) cdCommands envPaths dllPath.bat relPaths.sh - From 3e58c59377566c3a65cd5bc7a609ecf60a68ad19 Mon Sep 17 00:00:00 2001 From: Andrew Johnson Date: Thu, 19 Jan 2017 12:33:54 -0600 Subject: [PATCH 2/2] Fix CA server bind issue from Freddie Akeroyd --- documentation/RELEASE_NOTES.html | 27 +++-- src/cas/io/bsdSocket/casIntfIO.cc | 121 ++++++++++---------- src/libCom/osi/os/Darwin/osdSock.h | 3 +- src/libCom/osi/os/Linux/osdSock.h | 10 +- src/libCom/osi/os/RTEMS/osdSock.h | 7 +- src/libCom/osi/os/WIN32/osdSock.h | 5 +- src/libCom/osi/os/cygwin32/osdSock.h | 4 +- src/libCom/osi/os/freebsd/osdSock.h | 6 +- src/libCom/osi/os/iOS/osdSock.h | 1 + src/libCom/osi/os/solaris/osdSock.h | 8 +- src/libCom/osi/os/vxWorks/osdSock.h | 9 +- src/rsrv/caservertask.c | 161 ++++++++++++++------------- 12 files changed, 188 insertions(+), 174 deletions(-) diff --git a/documentation/RELEASE_NOTES.html b/documentation/RELEASE_NOTES.html index 98913581e..859ff7b29 100644 --- a/documentation/RELEASE_NOTES.html +++ b/documentation/RELEASE_NOTES.html @@ -13,6 +13,17 @@ +

Server bind issue on Windows

+ +

When a National Instruments network variables CA server is already running on +a Windows system and an IOC or PCAS server is started, the IOC's attempt to +bind a TCP socket to the CA server port number fails, but Windows returns a +different error status value than the IOC is expecting in that circumstance +(because the National Instruments code requests exclusive use of that port, +unlike the EPICS code) so the IOC fails to start properly. The relevent EPICS +bind() checks have now been updated so the IOC will request that a dynamic port +number be allocated for this TCP socket instead when this happens.

+

Checking Periodic Scan Rates

Code has been added to the IOC startup to better protect it against bad @@ -786,7 +797,7 @@ access monitor on the DLYA field; this happens twice during record processing if the ODLY field is larger than 0.

Timestamps from all seq record monitor events have been wrong since 1995 or -earlier, the time being provided was from the last time the record processed. +earlier, the time being provided was from the last time the record processed. Now the record timestamp will be updated between reading each DOL1..DOLA link and posting the monitor on the associated DO1..DOA field. The VAL field is never given a value by the record processing code, but is used for posting @@ -1018,7 +1029,7 @@ fixed in this release:

  • 717252 local caput causes ioc crash on win32
  • -
  • 750549 +
  • 750549 epicsTime has non-portable c++ static initialization
  • 753137 @@ -1372,7 +1383,7 @@ more extensive modifications.

    RTEMS 4.10 support

    -

    Added support for the latest release of RTEMS. There is no longer a +

    Added support for the latest release of RTEMS. There is no longer a distinction between executive and malloc memory pools. The new mount() API is used.

    @@ -1465,7 +1476,7 @@ doing a put

    These changes impact the Gateway (Proxy server) and other servers but not the IOC. -

    Mantis 360 fix - server is unresponsive for one of its clients, when +

    Mantis 360 fix - server is unresponsive for one of its clients, when async io postponed and in flow control mode

    Mantis 358 fix - PCAS service snap-in has no way to determine if its a put, @@ -1478,7 +1489,7 @@ controling motor through gw.

    Mantis 340 fix - leak when performing a read and conversion fails.

    -

    Mantis 348 fix - A call to 'assert (item.pList == this)' +

    Mantis 348 fix - A call to 'assert (item.pList == this)' failed in ../../../../src/cas/generic/st/ioBlocked.cc line 112

    Mantis 345 fix - Compilation warning: complaint about missing @@ -1494,7 +1505,7 @@ R3.13 client

    Mantis 329 fix - GW hang, pthread_mutex_lock failed: error Invalid argument message

    -

    Mantis 352 fix - gateway hangs temporarily under heavy load on 8-core +

    Mantis 352 fix - gateway hangs temporarily under heavy load on 8-core 64bit RHEL5

      @@ -2015,7 +2026,7 @@ tools to allow specifying the CA priority.

      GCC_EXEC_PREFIX references removed from configuration files

      -

      Definition of GCC_EXEC_PREFIX removed from CONFIG.CrossCommon and +

      Definition of GCC_EXEC_PREFIX removed from CONFIG.CrossCommon and unexport of GCC_EXEC_PREFIX removed from vxWorks and RTEMS builds.

      RTEMS Release

      @@ -3232,7 +3243,7 @@ was returned as -1.17549435E-38. This is now fixed.

      in a <name>_DBD macro definition. An include line will be placed in the <name>Include.dbd for each file specified in the <name>_DBD definition. If a Makefile contains

      -
              DBD=xxx.dbd 
      +
              DBD=xxx.dbd
               xxx_DBD = f1.dbd f2.dbd f3.dbd 

      an xxxInclude.dbd file will be created containing the lines

      diff --git a/src/cas/io/bsdSocket/casIntfIO.cc b/src/cas/io/bsdSocket/casIntfIO.cc index 16cd908e3..a284c1800 100644 --- a/src/cas/io/bsdSocket/casIntfIO.cc +++ b/src/cas/io/bsdSocket/casIntfIO.cc @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ // @@ -32,7 +32,7 @@ const unsigned caServerConnectPendQueueSize = 5u; // // casIntfIO::casIntfIO() // -casIntfIO::casIntfIO ( const caNetAddr & addrIn ) : +casIntfIO::casIntfIO ( const caNetAddr & addrIn ) : sock ( INVALID_SOCKET ), addr ( addrIn.getSockIP() ) { @@ -40,80 +40,79 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) : osiSocklen_t addrSize; bool portChange; - if ( ! osiSockAttach () ) { - throw S_cas_internal; - } + if ( ! osiSockAttach () ) { + throw S_cas_internal; + } - /* - * Setup the server socket - */ - this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP ); - if (this->sock==INVALID_SOCKET) { + /* + * Setup the server socket + */ + this->sock = epicsSocketCreate ( AF_INET, SOCK_STREAM, IPPROTO_TCP ); + if (this->sock == INVALID_SOCKET) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - printf ( "No socket error was %s\n", sockErrBuf ); - throw S_cas_noFD; - } + printf ( "No socket error was %s\n", sockErrBuf ); + throw S_cas_noFD; + } epicsSocketEnableAddressReuseDuringTimeWaitState ( this->sock ); - status = bind ( this->sock, - reinterpret_cast (&this->addr), - sizeof(this->addr) ); - if (status<0) { - if (SOCKERRNO == SOCK_EADDRINUSE) { - // - // enable assignment of a default port - // (so the getsockname() call below will - // work correctly) - // - this->addr.sin_port = ntohs (0); - status = bind( + status = bind ( this->sock, + reinterpret_cast (&this->addr), + sizeof(this->addr) ); + if (status < 0) { + if (SOCKERRNO == SOCK_EADDRINUSE || + SOCKERRNO == SOCK_EACCES) { + // + // enable assignment of a default port + // (so the getsockname() call below will + // work correctly) + // + this->addr.sin_port = ntohs (0); + status = bind( this->sock, reinterpret_cast (&this->addr), sizeof(this->addr) ); - } - if (status<0) { + } + if (status < 0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - char buf[64]; - ipAddrToA (&this->addr, buf, sizeof(buf)); - errPrintf ( S_cas_bindFail, - __FILE__, __LINE__, - "- bind TCP IP addr=%s failed because %s", - buf, sockErrBuf ); + char buf[64]; + ipAddrToA (&this->addr, buf, sizeof(buf)); + errlogPrintf ( "CAS: Socket bind TCP to %s failed with %s", + buf, sockErrBuf ); epicsSocketDestroy (this->sock); - throw S_cas_bindFail; - } + throw S_cas_bindFail; + } portChange = true; - } + } else { portChange = false; } - addrSize = ( osiSocklen_t ) sizeof (this->addr); - status = getsockname ( - this->sock, - reinterpret_cast ( &this->addr ), + addrSize = ( osiSocklen_t ) sizeof (this->addr); + status = getsockname ( + this->sock, + reinterpret_cast ( &this->addr ), &addrSize ); - if (status) { + if (status) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - errlogPrintf ( "CAS: getsockname() error %s\n", - sockErrBuf ); + errlogPrintf ( "CAS: getsockname() error %s\n", + sockErrBuf ); epicsSocketDestroy (this->sock); - throw S_cas_internal; - } + throw S_cas_internal; + } - // - // be sure of this now so that we can fetch the IP - // address and port number later - // + // + // be sure of this now so that we can fetch the IP + // address and port number later + // assert (this->addr.sin_family == AF_INET); if ( portChange ) { errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n"); - errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n", + errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n", ntohs (this->addr.sin_port) ); errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n"); errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" ); @@ -121,12 +120,12 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) : } status = listen(this->sock, caServerConnectPendQueueSize); - if(status < 0) { + if (status < 0) { char sockErrBuf[64]; epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - errlogPrintf ( "CAS: listen() error %s\n", sockErrBuf ); + errlogPrintf ( "CAS: listen() error %s\n", sockErrBuf ); epicsSocketDestroy (this->sock); - throw S_cas_internal; + throw S_cas_internal; } } @@ -135,17 +134,17 @@ casIntfIO::casIntfIO ( const caNetAddr & addrIn ) : // casIntfIO::~casIntfIO() { - if (this->sock != INVALID_SOCKET) { - epicsSocketDestroy (this->sock); - } + if (this->sock != INVALID_SOCKET) { + epicsSocketDestroy (this->sock); + } - osiSockRelease (); + osiSockRelease (); } // // newStreamIO::newStreamClient() // -casStreamOS *casIntfIO::newStreamClient ( caServerI & cas, +casStreamOS *casIntfIO::newStreamClient ( caServerI & cas, clientBufMemoryManager & bufMgr ) const { static bool oneMsgFlag = false; @@ -175,14 +174,14 @@ casStreamOS *casIntfIO::newStreamClient ( caServerI & cas, args.sock = newSock; casStreamOS * pOS = new casStreamOS ( cas, bufMgr, args ); if ( ! pOS ) { - errMessage ( S_cas_noMemory, + errMessage ( S_cas_noMemory, "unable to create data structures for a new client" ); epicsSocketDestroy ( newSock ); } else { if ( cas.getDebugLevel() > 0u ) { char pName[64u]; - + pOS->hostName ( pName, sizeof ( pName ) ); errlogPrintf ( "CAS: allocated client object for \"%s\"\n", pName ); } @@ -197,7 +196,7 @@ void casIntfIO::setNonBlocking() { int status; osiSockIoctl_t yes = true; - + status = socket_ioctl(this->sock, FIONBIO, &yes); // X aCC 392 if ( status < 0 ) { char sockErrBuf[64]; diff --git a/src/libCom/osi/os/Darwin/osdSock.h b/src/libCom/osi/os/Darwin/osdSock.h index 961b60663..0700114f0 100644 --- a/src/libCom/osi/os/Darwin/osdSock.h +++ b/src/libCom/osi/os/Darwin/osdSock.h @@ -1,7 +1,7 @@ /*************************************************************************\ * Copyright (c) 2002 The University of Saskatchewan * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * Author: Eric Norum @@ -38,6 +38,7 @@ typedef socklen_t osiSocklen_t; #define SOCK_ENOBUFS ENOBUFS #define SOCK_ECONNRESET ECONNRESET #define SOCK_ETIMEDOUT ETIMEDOUT +#define SOCK_EACCES EACCES #define SOCK_EADDRINUSE EADDRINUSE #define SOCK_ECONNREFUSED ECONNREFUSED #define SOCK_ECONNABORTED ECONNABORTED diff --git a/src/libCom/osi/os/Linux/osdSock.h b/src/libCom/osi/os/Linux/osdSock.h index e689526eb..36e84c0b1 100644 --- a/src/libCom/osi/os/Linux/osdSock.h +++ b/src/libCom/osi/os/Linux/osdSock.h @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -13,12 +13,12 @@ * Under Linux if we dont define _POSIX_C_SOURCE or _XOPEN_SOURCE * then none of the POSIX stuff (such as signals) can be used * with cc -v. However if one of _POSIX_C_SOURCE or _XOPEN_SOURCE - * are defined then we cant use the socket library. Therefore I - * have been adding the following in order to use POSIX signals + * are defined then we cant use the socket library. Therefore I + * have been adding the following in order to use POSIX signals * and also sockets on Linux with cc -v. What a pain.... * * #ifdef linux - * #define __EXTENSIONS__ + * #define __EXTENSIONS__ * #endif */ @@ -53,6 +53,7 @@ typedef socklen_t osiSocklen_t; #define SOCK_ENOBUFS ENOBUFS #define SOCK_ECONNRESET ECONNRESET #define SOCK_ETIMEDOUT ETIMEDOUT +#define SOCK_EACCES EACCES #define SOCK_EADDRINUSE EADDRINUSE #define SOCK_ECONNREFUSED ECONNREFUSED #define SOCK_ECONNABORTED ECONNABORTED @@ -82,4 +83,3 @@ typedef socklen_t osiSocklen_t; #define ifreq_size(pifreq) (sizeof(pifreq->ifr_name)) #endif /*osdSockH*/ - diff --git a/src/libCom/osi/os/RTEMS/osdSock.h b/src/libCom/osi/os/RTEMS/osdSock.h index 0f69b2a2c..e60c1bfd2 100644 --- a/src/libCom/osi/os/RTEMS/osdSock.h +++ b/src/libCom/osi/os/RTEMS/osdSock.h @@ -1,7 +1,7 @@ /*************************************************************************\ * Copyright (c) 2002 The University of Saskatchewan * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * RTEMS osdSock.h @@ -35,7 +35,7 @@ int select(int n, fd_set *readfds, fd_set *writefds, fd_set *exceptfds, str #ifdef __cplusplus } #endif - + typedef int SOCKET; #define INVALID_SOCKET (-1) #define SOCKERRNO errno @@ -49,6 +49,7 @@ typedef socklen_t osiSocklen_t; #define SOCK_ENOBUFS ENOBUFS #define SOCK_ECONNRESET ECONNRESET #define SOCK_ETIMEDOUT ETIMEDOUT +#define SOCK_EACCES EACCES #define SOCK_EADDRINUSE EADDRINUSE #define SOCK_ECONNREFUSED ECONNREFUSED #define SOCK_ECONNABORTED ECONNABORTED @@ -74,7 +75,7 @@ typedef socklen_t osiSocklen_t; #ifndef INADDR_NONE # define INADDR_NONE (0xffffffff) -#endif +#endif /* * For shutdown() diff --git a/src/libCom/osi/os/WIN32/osdSock.h b/src/libCom/osi/os/WIN32/osdSock.h index e6567e178..17f2afe4a 100644 --- a/src/libCom/osi/os/WIN32/osdSock.h +++ b/src/libCom/osi/os/WIN32/osdSock.h @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ #ifndef osdSockH @@ -14,7 +14,7 @@ #include /* - * winsock2.h changes the structure alignment to 4 if + * winsock2.h changes the structure alignment to 4 if * WIN32 isnt set which can be a source of confusion */ #ifndef WIN32 @@ -48,6 +48,7 @@ typedef int osiSocklen_t; #define SOCK_ENOBUFS WSAENOBUFS #define SOCK_ECONNRESET WSAECONNRESET #define SOCK_ETIMEDOUT WSAETIMEDOUT +#define SOCK_EACCES WSAEACCES #define SOCK_EADDRINUSE WSAEADDRINUSE #define SOCK_ECONNREFUSED WSAECONNREFUSED #define SOCK_ECONNABORTED WSAECONNABORTED diff --git a/src/libCom/osi/os/cygwin32/osdSock.h b/src/libCom/osi/os/cygwin32/osdSock.h index 460839a26..34ac5cc70 100644 --- a/src/libCom/osi/os/cygwin32/osdSock.h +++ b/src/libCom/osi/os/cygwin32/osdSock.h @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * cygwin32 specific include @@ -49,6 +49,7 @@ typedef int osiSocklen_t; #define SOCK_ENOBUFS ENOBUFS #define SOCK_ECONNRESET ECONNRESET #define SOCK_ETIMEDOUT ETIMEDOUT +#define SOCK_EACCES EACCES #define SOCK_EADDRINUSE EADDRINUSE #define SOCK_ECONNREFUSED ECONNREFUSED #define SOCK_ECONNABORTED ECONNABORTED @@ -66,4 +67,3 @@ typedef int osiSocklen_t; #define ifreq_size(pifreq) (sizeof(pifreq->ifr_name)) #endif /*osdSockH*/ - diff --git a/src/libCom/osi/os/freebsd/osdSock.h b/src/libCom/osi/os/freebsd/osdSock.h index 40df63631..b6858d678 100644 --- a/src/libCom/osi/os/freebsd/osdSock.h +++ b/src/libCom/osi/os/freebsd/osdSock.h @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ #ifndef osdSockH @@ -29,7 +29,7 @@ #define IPPORT_USERRESERVED 5000 #endif - + typedef int SOCKET; #define INVALID_SOCKET (-1) #define SOCKERRNO errno @@ -43,6 +43,7 @@ typedef socklen_t osiSocklen_t; #define SOCK_ENOBUFS ENOBUFS #define SOCK_ECONNRESET ECONNRESET #define SOCK_ETIMEDOUT ETIMEDOUT +#define SOCK_EACCES EACCES #define SOCK_EADDRINUSE EADDRINUSE #define SOCK_ECONNREFUSED ECONNREFUSED #define SOCK_ECONNABORTED ECONNABORTED @@ -76,4 +77,3 @@ typedef socklen_t osiSocklen_t; #endif #endif /*osdSockH*/ - diff --git a/src/libCom/osi/os/iOS/osdSock.h b/src/libCom/osi/os/iOS/osdSock.h index 136c8f8a9..bebc0ca45 100644 --- a/src/libCom/osi/os/iOS/osdSock.h +++ b/src/libCom/osi/os/iOS/osdSock.h @@ -39,6 +39,7 @@ typedef socklen_t osiSocklen_t; #define SOCK_ENOBUFS ENOBUFS #define SOCK_ECONNRESET ECONNRESET #define SOCK_ETIMEDOUT ETIMEDOUT +#define SOCK_EACCES EACCES #define SOCK_EADDRINUSE EADDRINUSE #define SOCK_ECONNREFUSED ECONNREFUSED #define SOCK_ECONNABORTED ECONNABORTED diff --git a/src/libCom/osi/os/solaris/osdSock.h b/src/libCom/osi/os/solaris/osdSock.h index bffcaf367..8b2893626 100644 --- a/src/libCom/osi/os/solaris/osdSock.h +++ b/src/libCom/osi/os/solaris/osdSock.h @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -39,7 +39,7 @@ typedef int osiSockIoctl_t; #if SOLARIS > 6 || defined ( _SOCKLEN_T ) typedef uint32_t osiSocklen_t; -#else +#else typedef int osiSocklen_t; #endif @@ -51,6 +51,7 @@ typedef int osiSockIoctl_t; #define SOCK_ENOBUFS ENOBUFS #define SOCK_ECONNRESET ECONNRESET #define SOCK_ETIMEDOUT ETIMEDOUT +#define SOCK_EACCES EACCES #define SOCK_EADDRINUSE EADDRINUSE #define SOCK_ECONNREFUSED ECONNREFUSED #define SOCK_ECONNABORTED ECONNABORTED @@ -79,9 +80,8 @@ typedef int osiSockIoctl_t; #ifndef INADDR_NONE # define INADDR_NONE (0xffffffff) -#endif +#endif #define ifreq_size(pifreq) (sizeof(pifreq->ifr_name)) #endif /*osdSockH*/ - diff --git a/src/libCom/osi/os/vxWorks/osdSock.h b/src/libCom/osi/os/vxWorks/osdSock.h index f220ea8bd..03ecb3153 100644 --- a/src/libCom/osi/os/vxWorks/osdSock.h +++ b/src/libCom/osi/os/vxWorks/osdSock.h @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* * vxWorks specific socket include @@ -44,7 +44,7 @@ int sysClkRateGet(void); #ifdef __cplusplus } #endif - + typedef int SOCKET; #define INVALID_SOCKET (-1) #define SOCKERRNO errno @@ -72,6 +72,7 @@ typedef int osiSocklen_t; #define SOCK_ENOBUFS ENOBUFS #define SOCK_ECONNRESET ECONNRESET #define SOCK_ETIMEDOUT ETIMEDOUT +#define SOCK_EACCES EACCES #define SOCK_EADDRINUSE EADDRINUSE #define SOCK_ECONNREFUSED ECONNREFUSED #define SOCK_ECONNABORTED ECONNABORTED @@ -92,7 +93,7 @@ typedef int osiSocklen_t; #ifndef INADDR_NONE # define INADDR_NONE (0xffffffff) -#endif +#endif #if defined(_SIZEOF_ADDR_IFREQ) # define ifreq_size(pifreq) _SIZEOF_ADDR_IFREQ(*pifreq) @@ -103,5 +104,3 @@ typedef int osiSocklen_t; #endif #endif /*osdSockH*/ - - diff --git a/src/rsrv/caservertask.c b/src/rsrv/caservertask.c index 51b7e99a8..7867babe6 100644 --- a/src/rsrv/caservertask.c +++ b/src/rsrv/caservertask.c @@ -4,7 +4,7 @@ * Copyright (c) 2002 The Regents of the University of California, as * Operator of Los Alamos National Laboratory. * EPICS BASE is distributed subject to a Software License Agreement found -* in file LICENSE that is included with this distribution. +* in file LICENSE that is included with this distribution. \*************************************************************************/ /* @@ -70,22 +70,22 @@ static void req_server (void *pParm) epicsSignalInstallSigPipeIgnore (); taskwdInsert ( epicsThreadGetIdSelf (), NULL, NULL ); - + rsrvCurrentClient = epicsThreadPrivateCreate (); if ( envGetConfigParamPtr ( &EPICS_CAS_SERVER_PORT ) ) { - ca_server_port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, + ca_server_port = envGetInetPortConfigParam ( &EPICS_CAS_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } else { - ca_server_port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, + ca_server_port = envGetInetPortConfigParam ( &EPICS_CA_SERVER_PORT, (unsigned short) CA_SERVER_PORT ); } if (IOC_sock != 0 && IOC_sock != INVALID_SOCKET) { epicsSocketDestroy ( IOC_sock ); } - + /* * Open the socket. Use ARPA Internet address format and stream * sockets. Format described in . @@ -100,53 +100,54 @@ static void req_server (void *pParm) /* Zero the sock_addr structure */ memset ( (void *) &serverAddr, 0, sizeof ( serverAddr ) ); serverAddr.sin_family = AF_INET; - serverAddr.sin_addr.s_addr = htonl (INADDR_ANY); + serverAddr.sin_addr.s_addr = htonl (INADDR_ANY); serverAddr.sin_port = htons ( ca_server_port ); /* get server's Internet address */ status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) ); - if ( status < 0 ) { - if ( SOCKERRNO == SOCK_EADDRINUSE ) { - /* - * enable assignment of a default port - * (so the getsockname() call below will - * work correctly) - */ - serverAddr.sin_port = ntohs (0); - status = bind ( IOC_sock, + if ( status < 0 ) { + if ( SOCKERRNO == SOCK_EADDRINUSE || + SOCKERRNO == SOCK_EACCES ) { + /* + * enable assignment of a default port + * (so the getsockname() call below will + * work correctly) + */ + serverAddr.sin_port = ntohs (0); + status = bind ( IOC_sock, (struct sockaddr *) &serverAddr, sizeof ( serverAddr ) ); - } - if ( status < 0 ) { + } + if ( status < 0 ) { char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( + epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - errlogPrintf ( "CAS: Socket bind error was \"%s\"\n", + errlogPrintf ( "CAS: Socket bind failed with %s\n", sockErrBuf ); epicsThreadSuspendSelf (); - } + } portChange = 1; - } + } else { portChange = 0; } - addrSize = ( osiSocklen_t ) sizeof ( serverAddr ); - status = getsockname ( IOC_sock, - (struct sockaddr *)&serverAddr, &addrSize); - if ( status ) { + addrSize = ( osiSocklen_t ) sizeof ( serverAddr ); + status = getsockname ( IOC_sock, + (struct sockaddr *)&serverAddr, &addrSize); + if ( status ) { char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( + epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); - errlogPrintf ( "CAS: getsockname() error %s\n", - sockErrBuf ); + errlogPrintf ( "CAS: getsockname() error %s\n", + sockErrBuf ); epicsThreadSuspendSelf (); - } + } ca_server_port = ntohs (serverAddr.sin_port); if ( portChange ) { errlogPrintf ( "cas warning: Configured TCP port was unavailable.\n"); - errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n", + errlogPrintf ( "cas warning: Using dynamically assigned TCP port %hu,\n", ca_server_port ); errlogPrintf ( "cas warning: but now two or more servers share the same UDP port.\n"); errlogPrintf ( "cas warning: Depending on your IP kernel this server may not be\n" ); @@ -189,13 +190,13 @@ static void req_server (void *pParm) clientSock = epicsSocketAccept ( IOC_sock, &sockAddr, &addLen ); if ( clientSock == INVALID_SOCKET ) { char sockErrBuf[64]; - epicsSocketConvertErrnoToString ( + epicsSocketConvertErrnoToString ( sockErrBuf, sizeof ( sockErrBuf ) ); errlogPrintf("CAS: Client accept error was \"%s\"\n", sockErrBuf ); epicsThreadSleep(15.0); continue; - } + } else { epicsThreadId id; struct client *pClient; @@ -279,14 +280,14 @@ int rsrv_init (void) castcp_ctl = ctlPause; /* - * go down two levels so that we are below + * go down two levels so that we are below * the TCP and event threads started on behalf * of individual clients */ - tbs = epicsThreadHighestPriorityLevelBelow ( + tbs = epicsThreadHighestPriorityLevelBelow ( epicsThreadPriorityCAServerLow, &priorityOfConnectDaemon ); if ( tbs == epicsThreadBooleanStatusSuccess ) { - tbs = epicsThreadHighestPriorityLevelBelow ( + tbs = epicsThreadHighestPriorityLevelBelow ( priorityOfConnectDaemon, &priorityOfConnectDaemon ); if ( tbs != epicsThreadBooleanStatusSuccess ) { priorityOfConnectDaemon = epicsThreadPriorityCAServerLow; @@ -327,7 +328,7 @@ int rsrv_pause (void) return RSRV_OK; } -static unsigned countChanListBytes ( +static unsigned countChanListBytes ( struct client *client, ELLLIST * pList ) { struct channel_in_use * pciu; @@ -346,7 +347,7 @@ static unsigned countChanListBytes ( return bytes_reserved; } -static void showChanList ( +static void showChanList ( struct client * client, ELLLIST * pList ) { unsigned i = 0u; @@ -354,7 +355,7 @@ static void showChanList ( epicsMutexMustLock ( client->chanListLock ); pciu = (struct channel_in_use *) pList->node.next; while ( pciu ){ - printf( "\t%s(%d%c%c)", + printf( "\t%s(%d%c%c)", pciu->addr.precord->name, ellCount ( &pciu->eventq ), asCheckGet ( pciu->asClientPVT ) ? 'r': '-', @@ -395,28 +396,28 @@ static void log_one_client (struct client *client, unsigned level) send_delay = epicsTimeDiffInSeconds(¤t,&client->time_at_last_send); recv_delay = epicsTimeDiffInSeconds(¤t,&client->time_at_last_recv); - printf ( "%s %s(%s): User=\"%s\", V%u.%u, %d Channels, Priority=%u\n", + printf ( "%s %s(%s): User=\"%s\", V%u.%u, %d Channels, Priority=%u\n", pproto, clientHostName, client->pHostName ? client->pHostName : "", client->pUserName ? client->pUserName : "", CA_MAJOR_PROTOCOL_REVISION, client->minor_version_number, - ellCount(&client->chanList) + + ellCount(&client->chanList) + ellCount(&client->chanPendingUpdateARList), client->priority ); if ( level >= 1 ) { - printf ("\tTask Id=%p, Socket FD=%d\n", - (void *) client->tid, client->sock); - printf( - "\tSecs since last send %6.2f, Secs since last receive %6.2f\n", + printf ("\tTask Id=%p, Socket FD=%d\n", + (void *) client->tid, client->sock); + printf( + "\tSecs since last send %6.2f, Secs since last receive %6.2f\n", send_delay, recv_delay); - printf( - "\tUnprocessed request bytes=%u, Undelivered response bytes=%u\n", + printf( + "\tUnprocessed request bytes=%u, Undelivered response bytes=%u\n", client->recv.cnt - client->recv.stk, - client->send.stk ); - printf( - "\tState=%s%s%s\n", + client->send.stk ); + printf( + "\tState=%s%s%s\n", state[client->disconnect?1:0], client->send.type == mbtLargeTCP ? " jumbo-send-buf" : "", client->recv.type == mbtLargeTCP ? " jumbo-recv-buf" : ""); @@ -425,9 +426,9 @@ static void log_one_client (struct client *client, unsigned level) if ( level >= 2u ) { unsigned bytes_reserved = 0; bytes_reserved += sizeof(struct client); - bytes_reserved += countChanListBytes ( + bytes_reserved += countChanListBytes ( client, & client->chanList ); - bytes_reserved += countChanListBytes ( + bytes_reserved += countChanListBytes ( client, & client->chanPendingUpdateARList ); printf( "\t%d bytes allocated\n", bytes_reserved); showChanList ( client, & client->chanList ); @@ -482,20 +483,20 @@ void epicsShareAPI casr (unsigned level) printf( "UDP Server:\n" ); log_one_client(prsrv_cast_client, level); } - + if (level>=2u) { bytes_reserved = 0u; - bytes_reserved += sizeof (struct client) * + bytes_reserved += sizeof (struct client) * freeListItemsAvail (rsrvClientFreeList); bytes_reserved += sizeof (struct channel_in_use) * freeListItemsAvail (rsrvChanFreeList); bytes_reserved += sizeof(struct event_ext) * freeListItemsAvail (rsrvEventFreeList); - bytes_reserved += MAX_TCP * + bytes_reserved += MAX_TCP * freeListItemsAvail ( rsrvSmallBufFreeListTCP ); - bytes_reserved += rsrvSizeofLargeBufTCP * + bytes_reserved += rsrvSizeofLargeBufTCP * freeListItemsAvail ( rsrvLargeBufFreeListTCP ); - bytes_reserved += rsrvSizeOfPutNotify ( 0 ) * + bytes_reserved += rsrvSizeOfPutNotify ( 0 ) * freeListItemsAvail ( rsrvPutNotifyFreeList ); printf( "There are currently %u bytes on the server's free list\n", (unsigned int) bytes_reserved); @@ -522,7 +523,7 @@ void epicsShareAPI casr (unsigned level) } } -/* +/* * destroy_client () */ void destroy_client ( struct client *client ) @@ -530,7 +531,7 @@ void destroy_client ( struct client *client ) if ( ! client ) { return; } - + if ( client->tid != 0 ) { taskwdRemove ( client->tid ); } @@ -600,12 +601,12 @@ void destroy_client ( struct client *client ) if ( client->pHostName ) { free ( client->pHostName ); - } + } freeListFree ( rsrvClientFreeList, client ); } -static void destroyAllChannels ( +static void destroyAllChannels ( struct client * client, ELLLIST * pList ) { if ( !client->chanListLock || !client->eventqLock ) { @@ -649,7 +650,7 @@ static void destroyAllChannels ( rsrvChannelCount--; UNLOCK_CLIENTQ; if ( status != S_bucket_success ) { - errPrintf ( status, __FILE__, __LINE__, + errPrintf ( status, __FILE__, __LINE__, "Bad id=%d at close", pciu->sid); } status = asRemoveClient(&pciu->asClientPVT); @@ -689,7 +690,7 @@ void destroy_tcp_client ( struct client *client ) if ( client->evuser ) { db_close_events (client->evuser); } - + destroy_client ( client ); } @@ -708,7 +709,7 @@ struct client * create_client ( SOCKET sock, int proto ) spaceAvailOnFreeList = freeListItemsAvail ( rsrvClientFreeList ) > 0 && freeListItemsAvail ( rsrvSmallBufFreeListTCP ) > 0; spaceNeeded = sizeof (struct client) + MAX_TCP; - if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) { + if ( ! ( osiSufficentSpaceInPool(spaceNeeded) || spaceAvailOnFreeList ) ) { epicsSocketDestroy ( sock ); epicsPrintf ("CAS: no space in pool for a new client (below max block thresh)\n"); return NULL; @@ -719,7 +720,7 @@ struct client * create_client ( SOCKET sock, int proto ) epicsSocketDestroy ( sock ); epicsPrintf ("CAS: no space in pool for a new client (alloc failed)\n"); return NULL; - } + } client->sock = sock; client->proto = proto; @@ -735,8 +736,8 @@ struct client * create_client ( SOCKET sock, int proto ) return NULL; } - client->pUserName = NULL; - client->pHostName = NULL; + client->pUserName = NULL; + client->pHostName = NULL; ellInit ( & client->chanList ); ellInit ( & client->chanPendingUpdateARList ); ellInit ( & client->putNotifyQue ); @@ -774,7 +775,7 @@ struct client * create_client ( SOCKET sock, int proto ) epicsTimeGetCurrent ( &client->time_at_last_recv ); client->minor_version_number = CA_UKN_MINOR_VERSION; client->recvBytesToDrain = 0u; - + return client; } @@ -789,10 +790,10 @@ void casAttachThreadToClient ( struct client *pClient ) void casExpandSendBuffer ( struct client *pClient, ca_uint32_t size ) { - if ( pClient->send.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP + if ( pClient->send.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP && size <= rsrvSizeofLargeBufTCP ) { int spaceAvailOnFreeList = freeListItemsAvail ( rsrvLargeBufFreeListTCP ) > 0; - if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) { + if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) { char *pNewBuf = ( char * ) freeListCalloc ( rsrvLargeBufFreeListTCP ); if ( pNewBuf ) { memcpy ( pNewBuf, pClient->send.buf, pClient->send.stk ); @@ -810,7 +811,7 @@ void casExpandRecvBuffer ( struct client *pClient, ca_uint32_t size ) if ( pClient->recv.type == mbtSmallTCP && rsrvSizeofLargeBufTCP > MAX_TCP && size <= rsrvSizeofLargeBufTCP) { int spaceAvailOnFreeList = freeListItemsAvail ( rsrvLargeBufFreeListTCP ) > 0; - if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) { + if ( osiSufficentSpaceInPool(rsrvSizeofLargeBufTCP) || spaceAvailOnFreeList ) { char *pNewBuf = ( char * ) freeListCalloc ( rsrvLargeBufFreeListTCP ); if ( pNewBuf ) { assert ( pClient->recv.cnt >= pClient->recv.stk ); @@ -847,26 +848,26 @@ struct client *create_tcp_client ( SOCKET sock ) * see TCP(4P) this seems to make unsolicited single events much * faster. I take care of queue up as load increases. */ - status = setsockopt ( sock, IPPROTO_TCP, TCP_NODELAY, + status = setsockopt ( sock, IPPROTO_TCP, TCP_NODELAY, (char *) &intTrue, sizeof (intTrue) ); if (status < 0) { errlogPrintf ( "CAS: TCP_NODELAY option set failed\n" ); destroy_client ( client ); return NULL; } - - /* + + /* * turn on KEEPALIVE so if the client crashes * this task will find out and exit */ - status = setsockopt ( sock, SOL_SOCKET, SO_KEEPALIVE, + status = setsockopt ( sock, SOL_SOCKET, SO_KEEPALIVE, (char *) &intTrue, sizeof (intTrue) ); if ( status < 0 ) { errlogPrintf ( "CAS: SO_KEEPALIVE option set failed\n" ); destroy_client ( client ); return NULL; } - + /* * some concern that vxWorks will run out of mBuf's * if this change is made @@ -874,8 +875,8 @@ struct client *create_tcp_client ( SOCKET sock ) * joh 11-10-98 */ #if 0 - /* - * set TCP buffer sizes to be synergistic + /* + * set TCP buffer sizes to be synergistic * with CA internal buffering */ i = MAX_MSG_SIZE; @@ -893,7 +894,7 @@ struct client *create_tcp_client ( SOCKET sock ) return NULL; } #endif - + addrSize = sizeof ( client->addr ); status = getpeername ( sock, (struct sockaddr *)&client->addr, &addrSize ); @@ -926,8 +927,8 @@ struct client *create_tcp_client ( SOCKET sock ) } } - status = db_start_events ( client->evuser, "CAS-event", - NULL, NULL, priorityOfEvents ); + status = db_start_events ( client->evuser, "CAS-event", + NULL, NULL, priorityOfEvents ); if ( status != DB_EVENT_OK ) { errlogPrintf ( "CAS: unable to start the event facility\n" ); destroy_tcp_client ( client );