osaf/libs/core/cplusplus/base/unix_client_socket.cc |  28 ++++-------
 osaf/libs/core/cplusplus/base/unix_client_socket.h  |   2 +-
 osaf/libs/core/cplusplus/base/unix_server_socket.cc |  19 +------
 osaf/libs/core/cplusplus/base/unix_server_socket.h  |   4 +-
 osaf/libs/core/cplusplus/base/unix_socket.cc        |  49 ++++++++++++++++++---
 osaf/libs/core/cplusplus/base/unix_socket.h         |  22 ++++++---
 6 files changed, 74 insertions(+), 50 deletions(-)


Make the UnixSocket class thread-safe by protecting Open() and Close() with a
mutex.

diff --git a/osaf/libs/core/cplusplus/base/unix_client_socket.cc 
b/osaf/libs/core/cplusplus/base/unix_client_socket.cc
--- a/osaf/libs/core/cplusplus/base/unix_client_socket.cc
+++ b/osaf/libs/core/cplusplus/base/unix_client_socket.cc
@@ -29,24 +29,18 @@ UnixClientSocket::UnixClientSocket(const
 UnixClientSocket::~UnixClientSocket() {
 }
 
-void UnixClientSocket::Open() {
-  if (fd() < 0) {
-    UnixSocket::Open();
-    if (fd() >= 0) {
-      int result;
-      int e;
-      do {
-        result = connect(fd(), addr(), addrlen());
-        e = errno;
-        if (result != 0 && (e == EALREADY || e == EINPROGRESS)) {
-          struct timespec delay{0, 10000000};
-          clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, nullptr);
-        }
-      } while (result != 0 && (e == EINTR || e == EALREADY
-                               || e == EINPROGRESS));
-      if (result != 0) Close();
+bool UnixClientSocket::OpenHook(int sock) {
+  int result;
+  int e;
+  do {
+    result = connect(sock, addr(), addrlen());
+    e = errno;
+    if (result != 0 && (e == EALREADY || e == EINPROGRESS)) {
+      struct timespec delay{0, 10000000};
+      clock_nanosleep(CLOCK_MONOTONIC, 0, &delay, nullptr);
     }
-  }
+  } while (result != 0 && (e == EINTR || e == EALREADY || e == EINPROGRESS));
+  return result == 0;
 }
 
 }  // namespace base
diff --git a/osaf/libs/core/cplusplus/base/unix_client_socket.h 
b/osaf/libs/core/cplusplus/base/unix_client_socket.h
--- a/osaf/libs/core/cplusplus/base/unix_client_socket.h
+++ b/osaf/libs/core/cplusplus/base/unix_client_socket.h
@@ -33,7 +33,7 @@ class UnixClientSocket : public UnixSock
   // from the file system.
   virtual ~UnixClientSocket();
  protected:
-  virtual void Open();
+  virtual bool OpenHook(int sock);
 };
 
 }  // namespace base
diff --git a/osaf/libs/core/cplusplus/base/unix_server_socket.cc 
b/osaf/libs/core/cplusplus/base/unix_server_socket.cc
--- a/osaf/libs/core/cplusplus/base/unix_server_socket.cc
+++ b/osaf/libs/core/cplusplus/base/unix_server_socket.cc
@@ -29,23 +29,12 @@ UnixServerSocket::UnixServerSocket(const
 UnixServerSocket::~UnixServerSocket() {
 }
 
-void UnixServerSocket::Open() {
-  if (fd() < 0) {
-    UnixSocket::Open();
-    if (fd() >= 0) {
-      int result = bind(fd(), addr(), addrlen());
-      if (result != 0) Close();
-    }
-  }
+bool UnixServerSocket::OpenHook(int sock) {
+  return bind(sock, addr(), addrlen()) == 0;
 }
 
-void UnixServerSocket::Close() {
-  if (fd() >= 0) {
-    int e = errno;
-    UnixSocket::Close();
-    unlink(path());
-    errno = e;
-  }
+void UnixServerSocket::CloseHook() {
+  unlink(path());
 }
 
 }  // namespace base
diff --git a/osaf/libs/core/cplusplus/base/unix_server_socket.h 
b/osaf/libs/core/cplusplus/base/unix_server_socket.h
--- a/osaf/libs/core/cplusplus/base/unix_server_socket.h
+++ b/osaf/libs/core/cplusplus/base/unix_server_socket.h
@@ -33,8 +33,8 @@ class UnixServerSocket : public UnixSock
   // file system.
   virtual ~UnixServerSocket();
  protected:
-  virtual void Open();
-  virtual void Close();
+  virtual bool OpenHook(int sock);
+  virtual void CloseHook();
 };
 
 }  // namespace base
diff --git a/osaf/libs/core/cplusplus/base/unix_socket.cc 
b/osaf/libs/core/cplusplus/base/unix_socket.cc
--- a/osaf/libs/core/cplusplus/base/unix_socket.cc
+++ b/osaf/libs/core/cplusplus/base/unix_socket.cc
@@ -19,40 +19,75 @@
 #include <sys/socket.h>
 #include <unistd.h>
 #include <cstring>
+#include "osaf/libs/core/common/include/osaf_utility.h"
 
 namespace base {
 
 UnixSocket::UnixSocket(const std::string& path) :
     fd_{-1},
-    addr_{AF_UNIX, {}} {
+    addr_{AF_UNIX, {}},
+    mutex_{} {
   if (path.size() < sizeof(addr_.sun_path)) {
     memcpy(addr_.sun_path, path.c_str(), path.size() + 1);
   } else {
     addr_.sun_path[0] = '\0';
   }
+  pthread_mutexattr_t attr;
+  int result = pthread_mutexattr_init(&attr);
+  if (result != 0) osaf_abort(result);
+  result = pthread_mutexattr_setprotocol(&attr, PTHREAD_PRIO_INHERIT);
+  if (result != 0) osaf_abort(result);
+  result = pthread_mutex_init(&mutex_, &attr);
+  if (result != 0) osaf_abort(result);
+  result = pthread_mutexattr_destroy(&attr);
+  if (result != 0) osaf_abort(result);
 }
 
-void UnixSocket::Open() {
-  if (fd_ < 0) {
+int UnixSocket::Open() {
+  osaf_mutex_lock_ordie(&mutex_);
+  int sock = fd_;
+  if (sock < 0) {
     if (addr_.sun_path[0] != '\0') {
-      fd_ = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
+      sock = socket(AF_UNIX, SOCK_DGRAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0);
+      if (sock >= 0 && !OpenHook(sock)) {
+        int e = errno;
+        close(sock);
+        sock = -1;
+        errno = e;
+      }
+      fd_ = sock;
     } else {
       errno = ENAMETOOLONG;
     }
   }
+  osaf_mutex_unlock_ordie(&mutex_);
+  return sock;
 }
 
 UnixSocket::~UnixSocket() {
   Close();
+  int result = pthread_mutex_destroy(&mutex_);
+  if (result != 0) osaf_abort(result);
 }
 
 void UnixSocket::Close() {
-  if (fd_ >= 0) {
+  osaf_mutex_lock_ordie(&mutex_);
+  int sock = fd_;
+  if (sock >= 0) {
     int e = errno;
-    close(fd_);
+    close(sock);
+    fd_ = -1;
+    CloseHook();
     errno = e;
-    fd_ = -1;
   }
+  osaf_mutex_unlock_ordie(&mutex_);
+}
+
+bool UnixSocket::OpenHook(int) {
+  return true;
+}
+
+void UnixSocket::CloseHook() {
 }
 
 }  // namespace base
diff --git a/osaf/libs/core/cplusplus/base/unix_socket.h 
b/osaf/libs/core/cplusplus/base/unix_socket.h
--- a/osaf/libs/core/cplusplus/base/unix_socket.h
+++ b/osaf/libs/core/cplusplus/base/unix_socket.h
@@ -18,6 +18,7 @@
 #ifndef OSAF_LIBS_CORE_CPLUSPLUS_BASE_UNIX_SOCKET_H_
 #define OSAF_LIBS_CORE_CPLUSPLUS_BASE_UNIX_SOCKET_H_
 
+#include <pthread.h>
 #include <sys/socket.h>
 #include <sys/un.h>
 #include <cerrno>
@@ -36,11 +37,12 @@ class UnixSocket {
   // handled by retrying the send() call in a loop. In case of other errors, 
the
   // socket will be closed.
   ssize_t Send(const void* buffer, size_t length) {
-    if (fd_ < 0) Open();
+    int sock = fd_;
+    if (sock < 0) sock = Open();
     ssize_t result = -1;
-    if (fd_ >= 0) {
+    if (sock >= 0) {
       do {
-        result = send(fd_, buffer, length, MSG_NOSIGNAL);
+        result = send(sock, buffer, length, MSG_NOSIGNAL);
       } while (result < 0 && errno == EINTR);
       if (result < 0 && errno != EAGAIN && errno != EWOULDBLOCK) Close();
     }
@@ -51,11 +53,12 @@ class UnixSocket {
   // is handled by retrying the recv() call in a loop. In case of other errors,
   // the socket will be closed.
   ssize_t Recv(void* buffer, size_t length) {
-    if (fd_ < 0) Open();
+    int sock = fd_;
+    if (sock < 0) sock = Open();
     ssize_t result = -1;
-    if (fd_ >= 0) {
+    if (sock >= 0) {
       do {
-        result = recv(fd_, buffer, length, 0);
+        result = recv(sock, buffer, length, 0);
       } while (result < 0 && errno == EINTR);
       if (result < 0 && errno != EAGAIN && errno != EWOULDBLOCK) Close();
     }
@@ -69,8 +72,10 @@ class UnixSocket {
 
  protected:
   explicit UnixSocket(const std::string& path);
-  virtual void Open();
-  virtual void Close();
+  int Open();
+  void Close();
+  virtual bool OpenHook(int sock);
+  virtual void CloseHook();
   const struct sockaddr* addr() const {
     return reinterpret_cast<const struct sockaddr*>(&addr_);
   }
@@ -80,6 +85,7 @@ class UnixSocket {
  private:
   int fd_;
   struct sockaddr_un addr_;
+  pthread_mutex_t mutex_;
 
   DELETE_COPY_AND_MOVE_OPERATORS(UnixSocket);
 };

------------------------------------------------------------------------------
Developer Access Program for Intel Xeon Phi Processors
Access to Intel Xeon Phi processor-based developer platforms.
With one year of Intel Parallel Studio XE.
Training and support from Colfax.
Order your platform today. http://sdm.link/xeonphi
_______________________________________________
Opensaf-devel mailing list
Opensaf-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/opensaf-devel

Reply via email to