make a pull request for issue 1188
diff --git a/src/session_client.c b/src/session_client.c
index 84f44c4..31cca1a 100644
--- a/src/session_client.c
+++ b/src/session_client.c
@@ -898,65 +898,107 @@
     return NULL;
 }
 
+/* A given timeout value limits the time how long the function blocks. If it has to block
+   only for some seconds, a socket connection might not yet have been fully established.
+   Therefore the active (pending) socket will be stored in *sock_pending, but the return
+   value will be -1. In such a case a subsequent invokation is required, by providing the
+   stored sock_pending, again.
+   In general, if this function returns -1, when a timeout has been given, this function
+   has to be invoked, until it returns a valid socket.
+ */
 int
-nc_sock_connect(const char* host, uint16_t port)
+nc_sock_connect(const char* host, uint16_t port, int timeout, int* sock_pending)
 {
-    int i, sock = -1, flags;
+    int i, flags, ret=0;
+    int sock = sock_pending?*sock_pending:-1;
+    fd_set  wset;
     struct addrinfo hints, *res_list, *res;
     char port_s[6]; /* length of string representation of short int */
+    struct timeval  ts;
 
-    snprintf(port_s, 6, "%u", port);
+    ts.tv_sec = timeout;
+    ts.tv_usec = 0;
 
-    /* Connect to a server */
-    memset(&hints, 0, sizeof hints);
-    hints.ai_family = AF_UNSPEC;
-    hints.ai_socktype = SOCK_STREAM;
-    hints.ai_protocol = IPPROTO_TCP;
-    i = getaddrinfo(host, port_s, &hints, &res_list);
-    if (i != 0) {
-        ERR("Unable to translate the host address (%s).", gai_strerror(i));
-        return -1;
-    }
+    VRB("nc_sock_connect(%s, %u, %d, %d)", host, port, timeout, sock);
 
-    for (res = res_list; res != NULL; res = res->ai_next) {
-        sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-        if (sock == -1) {
-            /* socket was not created, try another resource */
-            continue;
-        }
-
-        if (connect(sock, res->ai_addr, res->ai_addrlen) == -1) {
-            /* network connection failed, try another resource */
-            close(sock);
-            sock = -1;
-            continue;
-        }
-
-        /* make the socket non-blocking */
-        if (((flags = fcntl(sock, F_GETFL)) == -1) || (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)) {
-            ERR("Fcntl failed (%s).", strerror(errno));
-            close(sock);
-            freeaddrinfo(res_list);
+    /* no pending socket */
+    if (sock == -1) {
+        /* Connect to a server */
+        snprintf(port_s, 6, "%u", port);
+        memset(&hints, 0, sizeof hints);
+        hints.ai_family = AF_UNSPEC;
+        hints.ai_socktype = SOCK_STREAM;
+        hints.ai_protocol = IPPROTO_TCP;
+        i = getaddrinfo(host, port_s, &hints, &res_list);
+        if (i != 0) {
+            ERR("Unable to translate the host address (%s).", gai_strerror(i));
             return -1;
         }
 
-        /* enable keep-alive */
-        i = 1;
-        if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof i) == -1) {
-            ERR("Setsockopt failed (%s).", strerror(errno));
-            close(sock);
-            freeaddrinfo(res_list);
-            return -1;
+        for (res = res_list; res != NULL; res = res->ai_next) {
+            sock = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
+            if (sock == -1) {
+                /* socket was not created, try another resource */
+                continue;
+            }
+            /* make the socket non-blocking */
+            if (((flags = fcntl(sock, F_GETFL)) == -1) || (fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)) {
+                ERR("Fcntl failed (%s).", strerror(errno));
+                close(sock);
+                freeaddrinfo(res_list);
+                return -1;
+            }
+            /* enable keep-alive */
+            i = 1;
+            if (setsockopt(sock, SOL_SOCKET, SO_KEEPALIVE, &i, sizeof i) == -1) {
+                ERR("Setsockopt failed (%s).", strerror(errno));
+                close(sock);
+                freeaddrinfo(res_list);
+                return -1;
+            }
+            /* non-blocking connect! */
+            if (connect(sock, res->ai_addr, res->ai_addrlen) < 0) {
+                if (errno != EINPROGRESS) {
+                    /* network connection failed, try another resource */
+                    VRB("connect failed: (%s).", strerror(errno));
+                    close(sock);
+                    sock = -1;
+                    continue;
+                }
+            }
         }
-
-        /* we're done, network connection established */
-        break;
+        freeaddrinfo(res_list);
     }
-
+    /* new socket or pending socket */
     if (sock != -1) {
-        VRB("Successfully connected to %s:%s over %s.", host, port_s, (res->ai_family == AF_INET6) ? "IPv6" : "IPv4");
+
+        FD_ZERO(&wset);
+        FD_SET(sock, &wset);
+
+        if ((ret = select(sock + 1, NULL, &wset, NULL, (timeout != -1) ? &ts : NULL)) < 0) {
+            ERR("select failed: (%s).", strerror(errno));
+            close(sock);
+            return -1;
+        }
+
+        if (ret == 0) {   //we had a timeout
+            VRB("timed out after %ds (%s).", timeout, strerror(errno));
+            /* in that case we need to store it as pending for another attempt */
+            if (sock_pending) {
+                *sock_pending = sock;
+            } else {
+                close(sock);
+            }
+            return -1;
+        }
+
+        if (!FD_ISSET(sock, &wset)) {
+            ERR("FD_ISSET failed: (%s).", strerror(errno));
+            close(sock);
+            return -1;
+        }
+        VRB("Successfully connected to %s:%s.", host, port_s);
     }
-    freeaddrinfo(res_list);
 
     return sock;
 }
diff --git a/src/session_client_ssh.c b/src/session_client_ssh.c
index d9b7811..677867a 100644
--- a/src/session_client_ssh.c
+++ b/src/session_client_ssh.c
@@ -1514,7 +1514,7 @@
         ssh_options_set(session->ti.libssh.session, SSH_OPTIONS_HOST, host);
 
         /* create and connect socket */
-        sock = nc_sock_connect(host, port);
+        sock = nc_sock_connect(host, port, -1, NULL);
         if (sock == -1) {
             ERR("Unable to connect to %s:%u (%s).", host, port, strerror(errno));
             goto fail;
@@ -1663,7 +1663,7 @@
     }
 
     /* create and assign communication socket */
-    sock = nc_sock_connect(host, port);
+    sock = nc_sock_connect(host, port, -1, NULL);
     if (sock == -1) {
         ERR("Unable to connect to %s:%u (%s).", host, port, strerror(errno));
         goto fail;
diff --git a/src/session_client_tls.c b/src/session_client_tls.c
index fc780ad..5611aba 100644
--- a/src/session_client_tls.c
+++ b/src/session_client_tls.c
@@ -617,7 +617,7 @@
     }
 
     /* create and assign socket */
-    sock = nc_sock_connect(host, port);
+    sock = nc_sock_connect(host, port, -1, NULL);
     if (sock == -1) {
         ERR("Unable to connect to %s:%u (%s).", host, port, strerror(errno));
         goto fail;
diff --git a/src/session_p.h b/src/session_p.h
index 845fd3f..f28f392 100644
--- a/src/session_p.h
+++ b/src/session_p.h
@@ -230,6 +230,7 @@
             const char *name;
             const char *address;
             uint16_t port;
+            int sock_pending;
         } *ch_endpts;
         uint16_t ch_endpt_count;
         union {
@@ -516,9 +517,11 @@
  *
  * @param[in] host Hostname to connect to.
  * @param[in] port Port to connect on.
+ * @param[in] timeout for blocking the connect+select call (-1 for infinite).
+ * @param[in] sock_pending for exchanging the pending socket, if the blocking timeout was != -1
  * @return Connected socket or -1 on error.
  */
-int nc_sock_connect(const char *host, uint16_t port);
+int nc_sock_connect(const char *host, uint16_t port, int timeout, int* sock_pending);
 
 /**
  * @brief Accept a new socket connection.
diff --git a/src/session_server.c b/src/session_server.c
index 2f9aa5d..fa79a8e 100644
--- a/src/session_server.c
+++ b/src/session_server.c
@@ -467,6 +467,7 @@
 nc_server_init(struct ly_ctx *ctx)
 {
     const struct lys_node *rpc;
+    pthread_rwlockattr_t  attr;
 
     if (!ctx) {
         ERRARG("ctx");
@@ -492,6 +493,23 @@
     server_opts.new_session_id = 1;
     pthread_spin_init(&server_opts.sid_lock, PTHREAD_PROCESS_PRIVATE);
 
+    errno=0;
+
+    if (pthread_rwlockattr_init(&attr) == 0) {
+        if (pthread_rwlockattr_setkind_np(&attr, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP) == 0) {
+            if (pthread_rwlock_init(&server_opts.endpt_lock, &attr) != 0) {
+                ERR("%s: failed to init rwlock(%s).", __FUNCTION__, strerror(errno));
+            }
+            if (pthread_rwlock_init(&server_opts.ch_client_lock, &attr) != 0) {
+                ERR("%s: failed to init rwlock(%s).", __FUNCTION__, strerror(errno));
+            }
+        } else {
+            ERR("%s: failed set attribute (%s).", __FUNCTION__, strerror(errno));
+        }
+        pthread_rwlockattr_destroy(&attr);
+    } else {
+        ERR("%s: failed init attribute (%s).", __FUNCTION__, strerror(errno));
+    }
     return 0;
 }
 
@@ -2239,6 +2257,7 @@
     client->ch_endpts[client->ch_endpt_count - 1].name = lydict_insert(server_opts.ctx, endpt_name, 0);
     client->ch_endpts[client->ch_endpt_count - 1].address = NULL;
     client->ch_endpts[client->ch_endpt_count - 1].port = 0;
+    client->ch_endpts[client->ch_endpt_count - 1].sock_pending = -1;
 
     /* UNLOCK */
     nc_server_ch_client_unlock(client);
@@ -2269,6 +2288,9 @@
         for (i = 0; i < client->ch_endpt_count; ++i) {
             lydict_remove(server_opts.ctx, client->ch_endpts[i].name);
             lydict_remove(server_opts.ctx, client->ch_endpts[i].address);
+            if (client->ch_endpts[i].sock_pending != -1) {
+                close(client->ch_endpts[i].sock_pending);
+            }
         }
         free(client->ch_endpts);
         client->ch_endpts = NULL;
@@ -2654,10 +2676,12 @@
     int sock, ret;
     struct timespec ts_cur;
 
-    sock = nc_sock_connect(endpt->address, endpt->port);
+    sock = nc_sock_connect(endpt->address, endpt->port, 5, &endpt->sock_pending);
     if (sock < 0) {
         return NC_MSG_ERROR;
     }
+    /* no need to store the socket as pending any longer */
+    endpt->sock_pending = -1;
 
     *session = nc_new_session(NC_SERVER, 0);
     if (!(*session)) {