EPICS Controls Argonne National Laboratory

Experimental Physics and
Industrial Control System

1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  <20152016  2017  2018  2019  2020  2021  2022  2023  2024  Index 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  <20152016  2017  2018  2019  2020  2021  2022  2023  2024 
<== Date ==> <== Thread ==>

Subject: Re: CA Repeater: bind test err was "The operation completed successfully. "
From: Andrew Johnson <[email protected]>
To: <[email protected]>, <[email protected]>
Cc: [email protected]
Date: Tue, 10 Feb 2015 14:48:26 -0600
Hi Freddie, Lewis,

On 02/10/2015 10:54 AM, [email protected] wrote:
> I was referring to the epicsSocketDestroy() in makeSocket() rather
> than the one in verify(). I've checked on a windows machine and I can
> reproduce Lewis' behaviour - if I add a print of SOCKERRNO after a
> failed bind() in makeSocket() I see an error code of 10048, but
> printing it out again after the call to epicsSocketDestroy () in
> makeSocket() gives 0

My apologies, you were of course correct in what's happening, I should
have read your original message more closely.

>> On Feb 10, 2015, at 4:29 AM, [email protected] wrote:
>> 
>>> I think the bind() in makeSocket() is failing (as expected) but
>>> the
>> subsequent successful call to epicsSocketDestroy() in the same
>> function is clearing the error code, hence when the check is made
>> in repeaterClient::verify () rather than SOCK_EADDRINUSE it is
>> finding 0.  One way to fix it might be to change makeSocket() to
>> make a copy of any socket error code and then return that (or 0 on
>> success) rather than true/false

I have implemented this change in the attached patch. Unfortunately the
libCom osiSock.h interface didn't provide a way to convert an arbitrary
socket error number into a string, so I also had to extend the API to
add that functionality. Luckily there are only 2 implementations since
Windows is the only OS that doesn't use errno and strerror() for this.

This patch will not fix the original cause of Lewis' error from the
repeater, but it will at least result in the correct message being
displayed for it. If one of you could test this patch on Windows I will
commit the changes and publish it on the Known Problems page.

- Andrew
-- 
Doctorow's Law: Anytime someone puts a lock on something you own,
    against your wishes, and doesn't give you the key, they're
    not doing it for your benefit.
=== modified file 'src/ca/repeater.cpp'
--- src/ca/repeater.cpp	2013-05-16 18:33:31 +0000
+++ src/ca/repeater.cpp	2015-02-10 20:12:45 +0000
@@ -108,7 +108,7 @@
 /*
  * makeSocket()
  */
-static bool makeSocket ( unsigned short port, bool reuseAddr, SOCKET * pSock )
+static int makeSocket ( unsigned short port, bool reuseAddr, SOCKET * pSock )
 {
     int status;
 	union {
@@ -118,7 +118,7 @@
 
     SOCKET sock = epicsSocketCreate ( AF_INET, SOCK_DGRAM, 0 );     
     if ( sock == INVALID_SOCKET ) {
-        return false;
+        return SOCKERRNO;
     }
 
     /*
@@ -132,15 +132,16 @@
         bd.ia.sin_port = htons ( port );  
         status = bind ( sock, &bd.sa, (int) sizeof(bd) );
         if ( status < 0 ) {
+            status = SOCKERRNO;
             epicsSocketDestroy ( sock );
-            return false;
+            return status;
         }
         if ( reuseAddr ) {
             epicsSocketEnableAddressReuseDuringTimeWaitState ( sock );
         }
     }
     *pSock = sock;
-    return true;
+    return 0;
 }
 
 repeaterClient::repeaterClient ( const osiSockAddr &fromIn ) :
@@ -156,10 +157,10 @@
 {
     int status;
 
-    if ( ! makeSocket ( PORT_ANY, false, & this->sock ) ) {
+    if ( int sockerrno = makeSocket ( PORT_ANY, false, & this->sock ) ) {
         char sockErrBuf[64];
-        epicsSocketConvertErrnoToString ( 
-            sockErrBuf, sizeof ( sockErrBuf ) );
+        epicsSocketConvertErrorToString ( 
+            sockErrBuf, sizeof ( sockErrBuf ), sockerrno );
         fprintf ( stderr, "%s: no client sock because \"%s\"\n",
                 __FILE__, sockErrBuf );
         return false;
@@ -300,20 +301,20 @@
 bool repeaterClient::verify ()
 {
     SOCKET tmpSock;
-    bool success = makeSocket ( this->port (), false, & tmpSock );
-    if ( success ) {
+    int sockerrno = makeSocket ( this->port (), false, & tmpSock );
+    if ( sockerrno == 0 ) {
         epicsSocketDestroy ( tmpSock );
     }
     else {
-        if ( SOCKERRNO != SOCK_EADDRINUSE ) {
+        if ( sockerrno != SOCK_EADDRINUSE ) {
             char sockErrBuf[64];
-            epicsSocketConvertErrnoToString ( 
-                sockErrBuf, sizeof ( sockErrBuf ) );
+            epicsSocketConvertErrorToString (
+                sockErrBuf, sizeof ( sockErrBuf ), sockerrno );
             fprintf ( stderr, "CA Repeater: bind test err was \"%s\"\n", 
                 sockErrBuf );
         }
     }
-    return ! success;
+    return !!sockerrno; /* No socket errors => verification failed */
 }
 
 
@@ -387,10 +388,10 @@
 
         if ( ! init ) {
             SOCKET sock;
-            if ( ! makeSocket ( PORT_ANY, true, & sock ) ) {
+            if ( int sockerrno = makeSocket ( PORT_ANY, true, & sock ) ) {
                 char sockErrBuf[64];
-                epicsSocketConvertErrnoToString ( 
-                    sockErrBuf, sizeof ( sockErrBuf ) );
+                epicsSocketConvertErrorToString ( 
+                    sockErrBuf, sizeof ( sockErrBuf ), sockerrno );
                 fprintf ( stderr, "%s: Unable to create repeater bind test socket because \"%s\"\n",
                     __FILE__, sockErrBuf );
             }
@@ -511,18 +512,18 @@
 
     port = envGetInetPortConfigParam ( & EPICS_CA_REPEATER_PORT,
                                        static_cast <unsigned short> (CA_REPEATER_PORT) );
-    if ( ! makeSocket ( port, true, & sock ) ) {
+    if ( int sockerrno = makeSocket ( port, true, & sock ) ) {
         /*
          * test for server was already started
          */
-        if ( SOCKERRNO == SOCK_EADDRINUSE ) {
+        if ( sockerrno == SOCK_EADDRINUSE ) {
             osiSockRelease ();
             debugPrintf ( ( "CA Repeater: exiting because a repeater is already running\n" ) );
             return;
         }
         char sockErrBuf[64];
-        epicsSocketConvertErrnoToString ( 
-            sockErrBuf, sizeof ( sockErrBuf ) );
+        epicsSocketConvertErrorToString ( 
+            sockErrBuf, sizeof ( sockErrBuf ), sockerrno );
         fprintf ( stderr, "%s: Unable to create repeater socket because \"%s\" - fatal\n",
             __FILE__, sockErrBuf );
         osiSockRelease ();

=== modified file 'src/libCom/osi/os/WIN32/epicsSocketConvertErrnoToString.cpp'
--- src/libCom/osi/os/WIN32/epicsSocketConvertErrnoToString.cpp	2010-10-05 19:27:37 +0000
+++ src/libCom/osi/os/WIN32/epicsSocketConvertErrnoToString.cpp	2015-02-10 20:18:16 +0000
@@ -20,16 +20,15 @@
 #include "epicsStdio.h"
 
 /*
- * epicsSocketConvertErrnoToString ()
+ * epicsSocketConvertErrorToString ()
  */
-void epicsSocketConvertErrnoToString ( 
-        char * pBuf, unsigned bufSize )
+void epicsSocketConvertErrorToString (
+        char * pBuf, unsigned bufSize, int theSockError )
 {
     if ( bufSize ) {
 	    /*
 	     * this does not work on systems prior to W2K
 	     */
-        int theSockError = SOCKERRNO;
 	    DWORD success = FormatMessage ( 
 		    FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_MAX_WIDTH_MASK,
 		    NULL, theSockError,
@@ -45,3 +44,12 @@
 	    }
     }
 }
+
+/*
+ * epicsSocketConvertErrnoToString ()
+ */
+void epicsSocketConvertErrnoToString (
+        char * pBuf, unsigned bufSize )
+{
+    epicsSocketConvertErrorToString ( pBuf, bufSize, SOCKERRNO );
+}

=== modified file 'src/libCom/osi/os/default/epicsSocketConvertErrnoToString.cpp'
--- src/libCom/osi/os/default/epicsSocketConvertErrnoToString.cpp	2010-10-05 19:27:37 +0000
+++ src/libCom/osi/os/default/epicsSocketConvertErrnoToString.cpp	2015-02-10 20:17:50 +0000
@@ -22,14 +22,22 @@
 #include "osiSock.h"
 
 /*
- * epicsSocketConvertErrnoToString()
+ * epicsSocketConvertErrorToString()
  */
-void epicsSocketConvertErrnoToString ( 
-        char * pBuf, unsigned bufSize )
+void epicsSocketConvertErrorToString (
+        char * pBuf, unsigned bufSize, int theSockError )
 {
     if ( bufSize ) {
-        strncpy ( pBuf, strerror ( SOCKERRNO ), bufSize );
+        strncpy ( pBuf, strerror ( theSockError ), bufSize );
         pBuf[bufSize-1] = '\0';
     }
 }
 
+/*
+ * epicsSocketConvertErrnoToString()
+ */
+void epicsSocketConvertErrnoToString (
+        char * pBuf, unsigned bufSize )
+{
+    epicsSocketConvertErrorToString ( pBuf, bufSize, SOCKERRNO );
+}

=== modified file 'src/libCom/osi/osiSock.h'
--- src/libCom/osi/osiSock.h	2010-10-05 19:27:37 +0000
+++ src/libCom/osi/osiSock.h	2015-02-10 20:16:41 +0000
@@ -140,9 +140,11 @@
 epicsShareFunc void epicsShareAPI osiSockRelease (void);
 
 /*
- * convert socket error number to a string
+ * convert socket error numbers to a string
  */
-epicsShareFunc void epicsSocketConvertErrnoToString ( 
+epicsShareFunc void epicsSocketConvertErrorToString (
+        char * pBuf, unsigned bufSize, int error );
+epicsShareFunc void epicsSocketConvertErrnoToString (
         char * pBuf, unsigned bufSize );
 
 typedef union osiSockAddr {


Replies:
Re: CA Repeater: bind test err was "The operation completed successfully. " J. Lewis Muir
References:
CA Repeater: bind test err was "The operation completed successfully. " J. Lewis Muir
RE: CA Repeater: bind test err was "The operation completed successfully. " freddie.akeroyd
Re: CA Repeater: bind test err was "The operation completed successfully. " Johnson, Andrew N.
RE: CA Repeater: bind test err was "The operation completed successfully. " freddie.akeroyd

Navigate by Date:
Prev: Re: medm3.1.8 linker problem Ralph Lange
Next: Re: CA Repeater: bind test err was "The operation completed successfully. " J. Lewis Muir
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  <20152016  2017  2018  2019  2020  2021  2022  2023  2024 
Navigate by Thread:
Prev: RE: CA Repeater: bind test err was "The operation completed successfully. " freddie.akeroyd
Next: Re: CA Repeater: bind test err was "The operation completed successfully. " J. Lewis Muir
Index: 1994  1995  1996  1997  1998  1999  2000  2001  2002  2003  2004  2005  2006  2007  2008  2009  2010  2011  2012  2013  2014  <20152016  2017  2018  2019  2020  2021  2022  2023  2024 
ANJ, 16 Dec 2015 Valid HTML 4.01! · Home · News · About · Base · Modules · Extensions · Distributions · Download ·
· Search · EPICS V4 · IRMIS · Talk · Bugs · Documents · Links · Licensing ·