diff --git a/src/sftp/sftp.h b/src/sftp/sftp.h
index 8ce4535e7cc40f004647d2cfaa5f6b82ee3786f8..3a7366063712315c29f25a80e7daced26e99398e 100644
--- a/src/sftp/sftp.h
+++ b/src/sftp/sftp.h
@@ -250,6 +250,7 @@ bool sftpc_read(sftpc_state_t state, sftp_filehandle_t handle, uint64_t offset,
 bool sftpc_write(sftpc_state_t state, sftp_filehandle_t handle, uint64_t offset, sftp_str_t data);
 bool sftpc_reclaim(sftpc_state_t state);
 uint32_t sftpc_get_err(sftpc_state_t state);
+void sftpc_end(sftpc_state_t state);
 
 /* sftp_attr.c */
 sftp_file_attr_t sftp_fattr_alloc(void);
diff --git a/src/sftp/sftp_client.c b/src/sftp/sftp_client.c
index 43ed048d2698aa17e5cd770b25cc3c22ce4599af..cf1b1fad15086b75808e06bbd9309c935df6cab9 100644
--- a/src/sftp/sftp_client.c
+++ b/src/sftp/sftp_client.c
@@ -147,6 +147,10 @@ sftpc_finish(sftpc_state_t state)
 	if (state == NULL)
 		return;
 	pthread_mutex_lock(&state->mtx);
+	if (state->terminating == true) {
+		pthread_mutex_unlock(&state->mtx);
+		return;
+	}
 	state->terminating = true;
 	pthread_mutex_unlock(&state->mtx);
 	// TODO: Close all open handles
@@ -166,6 +170,17 @@ sftpc_finish(sftpc_state_t state)
 	sftp_free_rx_pkt(state->rxp);
 	sftp_free_tx_pkt(state->txp);
 	pthread_mutex_unlock(&state->mtx);
+}
+
+void
+sftpc_end(sftpc_state_t state)
+{
+	assert(state);
+	if (state == NULL)
+		return;
+	pthread_mutex_lock(&state->mtx);
+	assert(state->terminating);
+	pthread_mutex_unlock(&state->mtx);
 	pthread_mutex_destroy(&state->mtx);
 	free(state);
 }
diff --git a/src/syncterm/ssh.c b/src/syncterm/ssh.c
index aa4d73a7be9919a96610740789f246395d921f52..038bedf054878d89248d81b8c85c9c37da788d87 100644
--- a/src/syncterm/ssh.c
+++ b/src/syncterm/ssh.c
@@ -101,7 +101,6 @@ cryptlib_error_message(int status, const char *msg)
 static void
 close_sftp_channel(int chan)
 {
-	sftpc_state_t oldstate;
 	pthread_mutex_lock(&ssh_mutex);
 	if (chan != -1) {
 		FlushData(ssh_session);
@@ -118,12 +117,8 @@ close_sftp_channel(int chan)
 		}
 		sftp_channel = -1;
 	}
-	oldstate = sftp_state;
-	sftp_state = NULL;
 	pthread_mutex_unlock(&ssh_mutex);
-	if (oldstate != NULL) {
-		sftpc_finish(oldstate);
-	}
+	sftpc_finish(sftp_state);
 }
 
 static void
@@ -168,12 +163,13 @@ ssh_input_thread(void *args)
 	size_t buffered;
 	size_t buffer;
 	int    chan;
-	sftpc_state_t oldstate = NULL;
 	bool   both_gone = false;
+	bool   sftp_do_finish;
 
 	SetThreadName("SSH Input");
 	conn_api.input_thread_running = 1;
 	while (ssh_active && !conn_api.terminate) {
+		sftp_do_finish = false;
 		pthread_mutex_lock(&ssh_mutex);
 		if (FlushData(ssh_session) == CRYPT_ERROR_COMPLETE) {
 			pthread_mutex_unlock(&ssh_mutex);
@@ -185,8 +181,7 @@ ssh_input_thread(void *args)
 		}
 		if (sftp_channel != -1) {
 			if (!check_channel_open(&sftp_channel)) {
-				oldstate = sftp_state;
-				sftp_state = NULL;
+				sftp_do_finish = true;
 				sftp_channel = -1;
 			}
 		}
@@ -195,9 +190,9 @@ ssh_input_thread(void *args)
 		pthread_mutex_unlock(&ssh_mutex);
 		if (both_gone)
 			break;
-		if (oldstate != NULL) {
-			sftpc_finish(oldstate);
-			oldstate = NULL;
+		if (sftp_do_finish) {
+			sftpc_finish(sftp_state);
+			sftp_do_finish = false;
 		}
 		if (!socket_readable(ssh_sock, 100))
 			continue;
@@ -215,12 +210,8 @@ ssh_input_thread(void *args)
 		}
 		if (sftp_channel != -1) {
 			if (!check_channel_open(&sftp_channel)) {
-				sftpc_state_t oldstate = sftp_state;
-				sftp_state = NULL;
-				sftp_channel = -1;
 				pthread_mutex_unlock(&ssh_mutex);
-				sftpc_finish(oldstate);
-				oldstate = NULL;
+				sftpc_finish(sftp_state);
 				pthread_mutex_lock(&ssh_mutex);
 			}
 		}
@@ -307,10 +298,6 @@ ssh_input_thread(void *args)
 		FlushData(ssh_session);
 		pthread_mutex_unlock(&ssh_mutex);
 	}
-	if (oldstate != NULL) {
-		sftpc_finish(oldstate);
-		oldstate = NULL;
-	}
 	conn_api.input_thread_running = 2;
 }
 
@@ -449,7 +436,7 @@ key_not_present(sftp_filehandle_t f, const char *priv)
 	sftp_str_t r = NULL;
 	bool skipread = false;
 
-	do {
+	while (ssh_active) {
 		if (skipread) {
 			old_bufpos = 0;
 			skipread = false;
@@ -495,7 +482,8 @@ key_not_present(sftp_filehandle_t f, const char *priv)
 			memmove(buf, &buf[eol], bufpos - eol);
 			bufpos = bufpos - eol;
 		}
-	} while(1);
+	}
+	return false;
 }
 
 static void
@@ -520,6 +508,8 @@ add_public_key(void *vpriv)
 			}
 		}
 		pthread_mutex_unlock(&ssh_mutex);
+		if (!ssh_active)
+			break;
 		SLEEP(10);
 	};
 	if (!active) {
@@ -606,7 +596,7 @@ add_public_key(void *vpriv)
 		 * To avoid that, we'll sleep for a second to allow
 		 * the remote to close the channel if it wants to.
 		 */
-		for (unsigned sleep_count = 0; sleep_count < 100 && conn_api.terminate == 0; sleep_count++) {
+		for (unsigned sleep_count = 0; sleep_count < 100 && conn_api.terminate == 0 && ssh_active; sleep_count++) {
 			SLEEP(10);
 		}
 		pthread_mutex_lock(&ssh_tx_mutex);
@@ -646,12 +636,7 @@ add_public_key(void *vpriv)
 				}
 				sftpc_close(sftp_state, &f);
 			}
-			pthread_mutex_lock(&ssh_mutex);
-			sftpc_state_t oldstate = sftp_state;
-			sftp_state = NULL;
-			pthread_mutex_unlock(&ssh_mutex);
-			if (oldstate)
-				sftpc_finish(oldstate);
+			sftpc_finish(sftp_state);
 		}
 		close_sftp_channel(new_sftp_channel);
 	}
@@ -1022,16 +1007,21 @@ ssh_close(void)
 	cryptSetAttribute(ssh_session, CRYPT_OPTION_NET_READTIMEOUT, 1);
 	cryptSetAttribute(ssh_session, CRYPT_OPTION_NET_WRITETIMEOUT, 1);
 	conn_api.terminate = 1;
-	pthread_mutex_lock(&ssh_mutex);
-	int sc = sftp_channel;
-	pthread_mutex_unlock(&ssh_mutex);
-	close_sftp_channel(sc);
-	close_ssh_channel();
 	ssh_active = false;
+	if (sftp_state)
+		sftpc_finish(sftp_state);
 	while (conn_api.input_thread_running == 1 || conn_api.output_thread_running == 1 || pubkey_thread_running) {
 		conn_recv_upto(garbage, sizeof(garbage), 0);
 		SLEEP(1);
 	}
+	pthread_mutex_lock(&ssh_mutex);
+	int sc = sftp_channel;
+	pthread_mutex_unlock(&ssh_mutex);
+	if (sc != -1)
+		close_sftp_channel(sc);
+	if (sftp_state)
+		sftpc_end(sftp_state);
+	close_ssh_channel();
 	cryptDestroySession(ssh_session);
 	closesocket(ssh_sock);
 	ssh_sock = INVALID_SOCKET;