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