diff --git a/src/confdb/confdb.h b/src/confdb/confdb.h
index 4d61576..8c06d5b 100644
--- a/src/confdb/confdb.h
+++ b/src/confdb/confdb.h
@@ -78,6 +78,7 @@
 #define CONFDB_NSS_VETOED_SHELL  "vetoed_shells"
 #define CONFDB_NSS_ALLOWED_SHELL "allowed_shells"
 #define CONFDB_NSS_SHELL_FALLBACK "shell_fallback"
+#define CONFDB_NSS_IDLE_TIMEOUT "idle_timeout"
 
 /* PAM */
 #define CONFDB_PAM_CONF_ENTRY "config/pam"
diff --git a/src/responder/common/responder.h b/src/responder/common/responder.h
index 29bfff0..63581b8 100644
--- a/src/responder/common/responder.h
+++ b/src/responder/common/responder.h
@@ -90,6 +90,11 @@ struct resp_ctx {
     struct sss_names_ctx *names;
 
     void *pvt_ctx;
+
+    struct cli_ctx *cctx;
+
+    time_t idle_timeout;
+    struct tevent_timer *timer;
 };
 
 /* Needed for the NSS responder */
@@ -98,6 +103,9 @@ struct getent_ref_tracker {
 };
 
 struct cli_ctx {
+    struct cli_ctx *next;
+    struct cli_ctx *prev;
+
     struct tevent_context *ev;
     struct resp_ctx *rctx;
     int cfd;
@@ -120,6 +128,8 @@ struct cli_ctx {
     int netgrent_cur;
 
     time_t pam_timeout;
+
+    int active;
 };
 
 struct sss_cmd_table {
@@ -140,7 +150,8 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
                      struct sbus_interface *monitor_intf,
                      const char *cli_name,
                      struct sbus_interface *dp_intf,
-                     struct resp_ctx **responder_ctx);
+                     struct resp_ctx **responder_ctx,
+		     time_t idle_timeout);
 
 int sss_parse_name(TALLOC_CTX *memctx,
                    struct sss_names_ctx *snctx,
diff --git a/src/responder/common/responder_common.c b/src/responder/common/responder_common.c
index eb7a73f..db1cb6e 100644
--- a/src/responder/common/responder_common.c
+++ b/src/responder/common/responder_common.c
@@ -88,12 +88,88 @@ static errno_t set_close_on_exec(int fd)
     return EOK;
 }
 
+static void idle_handler(struct tevent_context *,
+			 struct tevent_timer *,
+			 struct timeval,
+			 void *);
+
+static void start_timer(struct resp_ctx *rctx, struct timeval *tvp)
+{
+    struct timeval tv;
+
+    if (rctx->idle_timeout <= 0) {
+	return;
+    }
+    if (rctx->timer) {
+	return;
+    }
+    if (!rctx->cctx) {
+	return;
+    }
+    if (!tvp) {
+	tvp = &tv;
+	tv = tevent_timeval_current();
+    }
+    tvp->tv_sec += rctx->idle_timeout;
+    rctx->timer = tevent_add_timer(rctx->cctx->ev, rctx,
+				   *tvp, idle_handler, rctx);
+    if (!rctx->timer) {
+	DEBUG(0, ("could not start idle timer\n"));
+    }
+}
+
+static void idle_handler(struct tevent_context *ev,
+			 struct tevent_timer *te,
+			 struct timeval current_time,
+			 void *data)
+{
+    struct resp_ctx *rctx = data;
+    struct cli_ctx *cctx;
+    int n = 0;
+
+    for (cctx = rctx->cctx; cctx; ) {
+	struct cli_ctx *cctx_next = cctx->next;
+
+	/*
+	 * Close the connection if there has been no
+	 * activity since we last checked and no
+	 * request is pending either.
+	 */
+	if (cctx->active || cctx->creq) {
+	    cctx->active = 0;
+	} else {
+	    talloc_free(cctx);
+	    n++;
+	}
+	cctx = cctx_next;
+    }
+    if (n) {
+	DEBUG(2, ("terminated %d idle connecions\n", n));
+    }
+
+    /*
+     * The timer event is freed by the library.
+     */
+    rctx->timer = NULL;
+    start_timer(rctx, &current_time);
+}
+
+static void client_add(struct cli_ctx *cctx)
+{
+    struct resp_ctx *rctx = cctx->rctx;
+
+    DLIST_ADD(rctx->cctx, cctx);
+    start_timer(rctx, NULL);
+}
+
+
 static int client_destructor(struct cli_ctx *ctx)
 {
     if (ctx->cfd > 0 && close(ctx->cfd) < 0) {
         DEBUG(0, ("client_destructor: close failed: [%d][%s]\n",
                   errno, strerror(errno)));
     }
+    DLIST_REMOVE(ctx->rctx->cctx, ctx);
     return 0;
 }
 
@@ -135,6 +211,8 @@ static void client_send(struct cli_ctx *cctx)
 {
     int ret;
 
+    cctx->active++;
+
     ret = sss_packet_send(cctx->creq->out, cctx->cfd);
     if (ret == EAGAIN) {
         /* not all data was sent, loop again */
@@ -158,6 +236,8 @@ static void client_recv(struct cli_ctx *cctx)
 {
     int ret;
 
+    cctx->active++;
+
     if (!cctx->creq) {
         cctx->creq = talloc_zero(cctx, struct cli_request);
         if (!cctx->creq) {
@@ -301,6 +381,8 @@ static void accept_priv_fd_handler(struct tevent_context *ev,
     cctx->ev = ev;
     cctx->rctx = rctx;
 
+    client_add(cctx);
+
     talloc_set_destructor(cctx, client_destructor);
 
     DEBUG(4, ("Client connected to privileged pipe!\n"));
@@ -359,6 +441,8 @@ static void accept_fd_handler(struct tevent_context *ev,
     cctx->ev = ev;
     cctx->rctx = rctx;
 
+    client_add(cctx);
+
     talloc_set_destructor(cctx, client_destructor);
 
     DEBUG(4, ("Client connected!\n"));
@@ -600,12 +684,15 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
                      struct sbus_interface *monitor_intf,
                      const char *cli_name,
                      struct sbus_interface *dp_intf,
-                     struct resp_ctx **responder_ctx)
+                     struct resp_ctx **responder_ctx,
+                     time_t idle_timeout)
 {
     struct resp_ctx *rctx;
     struct sss_domain_info *dom;
     int ret;
 
+    DEBUG(2, ("connection idle timeout %d\n", idle_timeout));
+
     rctx = talloc_zero(mem_ctx, struct resp_ctx);
     if (!rctx) {
         DEBUG(0, ("fatal error initializing resp_ctx\n"));
@@ -617,6 +704,7 @@ int sss_process_init(TALLOC_CTX *mem_ctx,
     rctx->sock_name = sss_pipe_name;
     rctx->priv_sock_name = sss_priv_pipe_name;
     rctx->confdb_service_path = confdb_service_path;
+    rctx->idle_timeout = idle_timeout;
 
     ret = confdb_get_domains(rctx->cdb, &rctx->domains);
     if (ret != EOK) {
diff --git a/src/responder/nss/nsssrv.c b/src/responder/nss/nsssrv.c
index cb0acfe..aa7ff49 100644
--- a/src/responder/nss/nsssrv.c
+++ b/src/responder/nss/nsssrv.c
@@ -258,6 +258,7 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
     struct nss_ctx *nctx;
     int ret, max_retries;
     int hret;
+    int idle_timeout;
 
     nctx = talloc_zero(mem_ctx, struct nss_ctx);
     if (!nctx) {
@@ -273,6 +274,13 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
 
     nss_cmds = get_nss_cmds();
 
+    ret = confdb_get_int(cdb, nctx, CONFDB_NSS_CONF_ENTRY,
+                         CONFDB_NSS_IDLE_TIMEOUT, 0, &idle_timeout);
+    if (ret != EOK) {
+        DEBUG(0, ("fatal error getting nss config idle_timeout\n"));
+        return ret;
+    }
+
     ret = sss_process_init(nctx, ev, cdb,
                            nss_cmds,
                            SSS_NSS_SOCKET_NAME, NULL,
@@ -281,7 +289,7 @@ int nss_process_init(TALLOC_CTX *mem_ctx,
                            NSS_SBUS_SERVICE_VERSION,
                            &monitor_nss_interface,
                            "NSS", &nss_dp_interface,
-                           &nctx->rctx);
+                           &nctx->rctx, idle_timeout);
     if (ret != EOK) {
         return ret;
     }
diff --git a/src/responder/pam/pamsrv.c b/src/responder/pam/pamsrv.c
index 91ee4a8..32ac527 100644
--- a/src/responder/pam/pamsrv.c
+++ b/src/responder/pam/pamsrv.c
@@ -125,7 +125,7 @@ static int pam_process_init(TALLOC_CTX *mem_ctx,
                            SSS_PAM_SBUS_SERVICE_VERSION,
                            &monitor_pam_interface,
                            "PAM", &pam_dp_interface,
-                           &pctx->rctx);
+                           &pctx->rctx, 0);
     if (ret != EOK) {
         goto done;
     }
diff --git a/src/sss_client/common.c b/src/sss_client/common.c
index 5397e4d..e0b934d 100644
--- a/src/sss_client/common.c
+++ b/src/sss_client/common.c
@@ -132,16 +132,25 @@ static enum nss_status sss_nss_send_req(enum sss_cli_command cmd,
             return NSS_STATUS_UNAVAIL;
         }
 
+	/*
+	 * Note we set MSG_NOSIGNAL to avoid
+	 * having to fiddle with signal masks
+	 * but also do not want to die in case
+	 * SIGPIPE gets raised and the application
+	 * does not handle it.
+	 */
         errno = 0;
         if (datasent < SSS_NSS_HEADER_SIZE) {
-            res = write(sss_cli_sd,
-                        (char *)header + datasent,
-                        SSS_NSS_HEADER_SIZE - datasent);
+            res = send(sss_cli_sd,
+		       (char *)header + datasent,
+		       SSS_NSS_HEADER_SIZE - datasent,
+		       MSG_NOSIGNAL);
         } else {
             rdsent = datasent - SSS_NSS_HEADER_SIZE;
-            res = write(sss_cli_sd,
-                        (const char *)rd->data + rdsent,
-                        rd->len - rdsent);
+            res = send(sss_cli_sd,
+		       (const char *)rd->data + rdsent,
+		       rd->len - rdsent,
+		       MSG_NOSIGNAL);
         }
         error = errno;
 
@@ -363,12 +372,11 @@ static enum nss_status sss_nss_make_request_nochecks(
  * 0-3: 32bit unsigned version number
  */
 
-static int sss_nss_check_version(const char *socket_name)
+static int sss_nss_check_version(const char *socket_name, int *errnop)
 {
     uint8_t *repbuf;
     size_t replen;
     enum nss_status nret;
-    int errnop;
     int res = NSS_STATUS_UNAVAIL;
     uint32_t expected_version;
     struct sss_cli_req_data req;
@@ -379,6 +387,7 @@ static int sss_nss_check_version(const char *socket_name)
                strcmp(socket_name, SSS_PAM_PRIV_SOCKET_NAME) == 0) {
         expected_version = SSS_PAM_PROTOCOL_VERSION;
     } else {
+	*errnop = EFAULT;
         return NSS_STATUS_UNAVAIL;
     }
 
@@ -386,17 +395,16 @@ static int sss_nss_check_version(const char *socket_name)
     req.data = &expected_version;
 
     nret = sss_nss_make_request_nochecks(SSS_GET_VERSION, &req,
-                                         &repbuf, &replen, &errnop);
+                                         &repbuf, &replen, errnop);
     if (nret != NSS_STATUS_SUCCESS) {
         return nret;
     }
 
-    if (!repbuf) {
-        return res;
-    }
-
-    if (((uint32_t *)repbuf)[0] == expected_version) {
+    if (repbuf && ((uint32_t *)repbuf)[0] == expected_version) {
+	*errnop = 0;
         res = NSS_STATUS_SUCCESS;
+    } else {
+	*errnop = EFAULT;
     }
 
     free(repbuf);
@@ -670,12 +678,12 @@ static enum sss_status sss_cli_check_socket(int *errnop, const char *socket_name
 
     sss_cli_sd = mysd;
 
-    if (sss_nss_check_version(socket_name) == NSS_STATUS_SUCCESS) {
+    ret = sss_nss_check_version(socket_name, errnop);
+    if (ret == NSS_STATUS_SUCCESS) {
         return SSS_STATUS_SUCCESS;
     }
 
     sss_cli_close_socket();
-    *errnop = EFAULT;
     return SSS_STATUS_UNAVAIL;
 }
 
@@ -686,8 +694,9 @@ enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
                       uint8_t **repbuf, size_t *replen,
                       int *errnop)
 {
-    enum sss_status ret;
     char *envval;
+    enum nss_status ret = NSS_STATUS_UNAVAIL;
+    int i;
 
     /* avoid looping in the nss daemon */
     envval = getenv("_SSS_LOOPS");
@@ -695,12 +704,28 @@ enum nss_status sss_nss_make_request(enum sss_cli_command cmd,
         return NSS_STATUS_NOTFOUND;
     }
 
-    ret = sss_cli_check_socket(errnop, SSS_NSS_SOCKET_NAME);
-    if (ret != SSS_STATUS_SUCCESS) {
-        return NSS_STATUS_UNAVAIL;
-    }
 
-    return sss_nss_make_request_nochecks(cmd, rd, repbuf, replen, errnop);
+    for (i = 0; i < 2; i++) {
+	enum sss_status err;
+
+	err = sss_cli_check_socket(errnop, SSS_NSS_SOCKET_NAME);
+	if (err == SSS_STATUS_SUCCESS) {
+	    ret = sss_nss_make_request_nochecks(cmd, rd, repbuf,
+						replen, errnop);
+	    if (ret == NSS_STATUS_SUCCESS) {
+		break;
+	    }
+	    if (ret != NSS_STATUS_UNAVAIL) {
+		break;
+	    }
+	} else if (err != SSS_STATUS_UNAVAIL) {
+	    break;
+	}
+	if (*errnop != 0 && *errnop != EPIPE) {
+	    break;
+	}
+    }
+    return ret;
 }
 
 errno_t check_server_cred(int sockfd)
