diff --git a/lib/extension.c b/lib/extension.c
index 19d68cb5f80f3b25159a63bee0f6f7d30010921a..176faf0e8861a1e8f274471c80c0047eba6d5a5f 100644
--- a/lib/extension.c
+++ b/lib/extension.c
@@ -130,8 +130,10 @@ lws_issue_raw_ext_access(struct libwebsocket *wsi,
 		if (eff_buf.token_len) {
 			n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
 							    eff_buf.token_len);
-			if (n < 0)
+			if (n < 0) {
+				lwsl_info("closing from ext access\n");
 				return -1;
+			}
 
 			/* always either sent it all or privately buffered */
 		}
diff --git a/lib/libwebsockets.c b/lib/libwebsockets.c
index d8fa1e34fceb3beff34620274567fc8e8639b715..d2f06af8f4f22e22b60bd838976ae6892eea1dbf 100644
--- a/lib/libwebsockets.c
+++ b/lib/libwebsockets.c
@@ -53,13 +53,30 @@ libwebsocket_close_and_free_session(struct libwebsocket_context *context,
 
 	old_state = wsi->state;
 
-	if (old_state == WSI_STATE_DEAD_SOCKET)
+	switch (old_state) {
+	case WSI_STATE_DEAD_SOCKET:
 		return;
 
 	/* we tried the polite way... */
-	if (old_state == WSI_STATE_AWAITING_CLOSE_ACK)
+	case WSI_STATE_AWAITING_CLOSE_ACK:
 		goto just_kill_connection;
 
+	case WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE:
+		if (wsi->truncated_send_len) {
+			libwebsocket_callback_on_writable(context, wsi);
+			return;
+		}
+		lwsl_info("wsi %p completed WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
+		goto just_kill_connection;
+	default:
+		if (wsi->truncated_send_len) {
+			lwsl_info("wsi %p entering WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE\n", wsi);
+			wsi->state = WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE;
+			return;
+		}
+		break;
+	}
+
 	wsi->u.ws.close_reason = reason;
 
 	if (wsi->mode == LWS_CONNMODE_WS_CLIENT_WAITING_CONNECT ||
diff --git a/lib/output.c b/lib/output.c
index 6c060c999fe06589dec3d58bbcd078e646b3afc2..b2359549fa17887e9f574e9d0a0a3e7409638fde 100644
--- a/lib/output.c
+++ b/lib/output.c
@@ -99,6 +99,10 @@ int lws_issue_raw(struct libwebsocket *wsi, unsigned char *buf, size_t len)
 	
 	if (!len)
 		return 0;
+	/* just ignore sends after we cleared the truncation buffer */
+	if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE &&
+						!wsi->truncated_send_len)
+		return len;
 
 	if (wsi->truncated_send_len && (buf < wsi->truncated_send_malloc ||
 			buf > (wsi->truncated_send_malloc +
@@ -149,6 +153,9 @@ handle_truncated_send:
 			lwsl_info("***** %x partial send completed\n", wsi);
 			/* done with it, but don't free it */
 			n = real_len;
+			if (wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE)
+				lwsl_info("***** %x signalling to close now\n", wsi);
+				return -1; /* retry closing now */
 		}
 		/* always callback on writeable */
 		libwebsocket_callback_on_writable(
@@ -480,9 +487,12 @@ LWS_VISIBLE int libwebsockets_serve_http_file_fragment(
 	while (!lws_send_pipe_choked(wsi)) {
 
 		if (wsi->truncated_send_len) {
-			lws_issue_raw(wsi, wsi->truncated_send_malloc +
+			if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
 					wsi->truncated_send_offset,
-						       wsi->truncated_send_len);
+						       wsi->truncated_send_len) < 0) {
+				lwsl_info("closing from libwebsockets_serve_http_file_fragment\n");
+				return -1;
+			}
 			continue;
 		}
 
diff --git a/lib/private-libwebsockets.h b/lib/private-libwebsockets.h
index be6c2d936444a4d6122b551eb953b52c6524f3d7..94bd227013328f23e0c4dc713d21947d7b817ab8 100644
--- a/lib/private-libwebsockets.h
+++ b/lib/private-libwebsockets.h
@@ -287,6 +287,7 @@ enum lws_connection_states {
 	WSI_STATE_CLIENT_UNCONNECTED,
 	WSI_STATE_RETURNED_CLOSE_ALREADY,
 	WSI_STATE_AWAITING_CLOSE_ACK,
+	WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE,
 };
 
 enum lws_rx_parse_state {
diff --git a/lib/server.c b/lib/server.c
index ed2dd202e0c8cd014d654c0a62cdc5cdfce759dc..2d2ffb303d39e9b9a17e4ade0fd869cc6aa4dc27 100644
--- a/lib/server.c
+++ b/lib/server.c
@@ -506,9 +506,12 @@ int lws_server_socket_service(struct libwebsocket_context *context,
 
 		if (wsi->truncated_send_malloc) {
 			if (pollfd->revents & LWS_POLLOUT)
-				lws_issue_raw(wsi, wsi->truncated_send_malloc +
+				if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
 					wsi->truncated_send_offset,
-							wsi->truncated_send_len);
+							wsi->truncated_send_len) < 0) {
+					lwsl_info("closing from socket service\n");
+					return -1;
+				}
 			/*
 			 * we can't afford to allow input processing send
 			 * something new, so spin around he event loop until
@@ -539,16 +542,20 @@ int lws_server_socket_service(struct libwebsocket_context *context,
 				break;
 			}
 
-			/* hm this may want to send (via HTTP callback for example) */
+			/* just ignore incoming if waiting for close */
+			if (wsi->state != WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) {
+			
+				/* hm this may want to send (via HTTP callback for example) */
 
-			n = libwebsocket_read(context, wsi,
-						context->service_buffer, len);
-			if (n < 0)
-				/* we closed wsi */
-				return 0;
+				n = libwebsocket_read(context, wsi,
+							context->service_buffer, len);
+				if (n < 0)
+					/* we closed wsi */
+					return 0;
 
-			/* hum he may have used up the writability above */
-			break;
+				/* hum he may have used up the writability above */
+				break;
+			}
 		}
 
 		/* this handles POLLOUT for http serving fragments */
diff --git a/lib/service.c b/lib/service.c
index 5edc2a32a096ce1741531c422369b2ec43fdc57a..85b6753d36439520f2000c676ad943da7f83833b 100644
--- a/lib/service.c
+++ b/lib/service.c
@@ -34,9 +34,12 @@ lws_handle_POLLOUT_event(struct libwebsocket_context *context,
 	/* pending truncated sends have uber priority */
 
 	if (wsi->truncated_send_len) {
-		lws_issue_raw(wsi, wsi->truncated_send_malloc +
+		if (lws_issue_raw(wsi, wsi->truncated_send_malloc +
 				wsi->truncated_send_offset,
-						wsi->truncated_send_len);
+						wsi->truncated_send_len) < 0) {
+			lwsl_info("lws_handle_POLLOUT_event signalling to close\n");
+			return -1;
+		}
 		/* leave POLLOUT active either way */
 		return 0;
 	}
@@ -87,8 +90,10 @@ lws_handle_POLLOUT_event(struct libwebsocket_context *context,
 		if (eff_buf.token_len) {
 			n = lws_issue_raw(wsi, (unsigned char *)eff_buf.token,
 							     eff_buf.token_len);
-			if (n < 0)
+			if (n < 0) {
+				lwsl_info("closing from POLLOUT spill\n");
 				return -1;
+			}
 			/*
 			 * Keep amount spilled small to minimize chance of this
 			 */
@@ -340,6 +345,8 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
 	case LWS_CONNMODE_SERVER_LISTENER:
 	case LWS_CONNMODE_SSL_ACK_PENDING:
 		n = lws_server_socket_service(context, wsi, pollfd);
+		if (n < 0)
+			goto close_and_handled;
 		goto handled;
 
 	case LWS_CONNMODE_WS_SERVING:
@@ -348,7 +355,8 @@ libwebsocket_service_fd(struct libwebsocket_context *context,
 		/* the guy requested a callback when it was OK to write */
 
 		if ((pollfd->revents & LWS_POLLOUT) &&
-			wsi->state == WSI_STATE_ESTABLISHED &&
+			(wsi->state == WSI_STATE_ESTABLISHED ||
+				wsi->state == WSI_STATE_FLUSHING_STORED_SEND_BEFORE_CLOSE) &&
 			   lws_handle_POLLOUT_event(context, wsi, pollfd)) {
 			lwsl_info("libwebsocket_service_fd: closing\n");
 			goto close_and_handled;