Browse Source

Send "SIGPIPE" (KTP_STDOUT_CLOSE) to server when client's pager is closed

Serj Kalichev 7 months ago
parent
commit
e20d300aa3
5 changed files with 43 additions and 2 deletions
  1. 3 2
      bin/klish/interactive.c
  2. 1 0
      klish/ktp.h
  3. 10 0
      klish/ktp/ktp_session.c
  4. 28 0
      klish/ktp/ktpd_session.c
  5. 1 0
      klish/ktp_session.h

+ 3 - 2
bin/klish/interactive.c

@@ -271,7 +271,7 @@ bool_t cmd_ack_cb(ktp_session_t *ktp, const faux_msg_t *msg, void *udata)
 	faux_error_free(error);
 
 	// Wait for pager
-	if (ctx->pager_working == TRI_TRUE) {
+	if (ctx->pager_working != TRI_UNDEFINED) {
 		pclose(ctx->pager_pipe);
 		ctx->pager_working = TRI_UNDEFINED;
 		ctx->pager_pipe = NULL;
@@ -740,7 +740,8 @@ static bool_t interactive_stdout_cb(ktp_session_t *ktp, const char *line, size_t
 		if (faux_write_block(fileno(ctx->pager_pipe), line, len) <= 0) {
 			// If we can't write to pager pipe then send
 			// "SIGPIPE" to server. Pager is finished or broken.
-			// TODO: Send "SIGPIPE" to server
+			ktp_session_stdout_close(ktp);
+			ctx->pager_working = TRI_FALSE;
 			return BOOL_TRUE; // Don't break the loop
 		}
 

+ 1 - 0
klish/ktp.h

@@ -27,6 +27,7 @@ typedef enum {
 	KTP_AUTH = 'a',
 	KTP_AUTH_ACK = 'A',
 	KTP_KEEPALIVE = 'k',
+	KTP_STDOUT_CLOSE = 'O',
 } ktp_cmd_e;
 
 

+ 10 - 0
klish/ktp/ktp_session.c

@@ -695,6 +695,16 @@ bool_t ktp_session_stdin(ktp_session_t *ktp, const char *line, size_t line_len)
 }
 
 
+bool_t ktp_session_stdout_close(ktp_session_t *ktp)
+{
+	if (!ktp_session_req(ktp, KTP_STDOUT_CLOSE, NULL, 0,
+		NULL, BOOL_TRUE, BOOL_FALSE))
+		return BOOL_FALSE;
+
+	return BOOL_TRUE;
+}
+
+
 bool_t ktp_session_retcode(ktp_session_t *ktp, int *retcode)
 {
 	if (!ktp)

+ 28 - 0
klish/ktp/ktpd_session.c

@@ -1010,6 +1010,27 @@ static bool_t ktpd_session_process_notification(ktpd_session_t *ktpd, faux_msg_t
 }
 
 
+static bool_t ktpd_session_process_stdout_close(ktpd_session_t *ktpd,
+	faux_msg_t *msg)
+{
+	int fd = -1;
+
+	assert(ktpd);
+	assert(msg);
+
+	if (!ktpd->exec)
+		return BOOL_FALSE;
+	fd = kexec_stdout(ktpd->exec);
+	if (fd < 0)
+		return BOOL_FALSE;
+	close(fd);
+//	kexec_set_stdout(ktpd->exec, -1);
+syslog(LOG_ERR, "Close stdout");
+
+	return BOOL_TRUE;
+}
+
+
 static bool_t ktpd_session_dispatch(ktpd_session_t *ktpd, faux_msg_t *msg)
 {
 	uint16_t cmd = 0;
@@ -1068,6 +1089,13 @@ static bool_t ktpd_session_dispatch(ktpd_session_t *ktpd, faux_msg_t *msg)
 	case KTP_NOTIFICATION:
 		ktpd_session_process_notification(ktpd, msg);
 		break;
+	case KTP_STDOUT_CLOSE:
+		if (ktpd->state != KTPD_SESSION_STATE_WAIT_FOR_PROCESS) {
+			err = "No active command is running";
+			break;
+		}
+		ktpd_session_process_stdout_close(ktpd, msg);
+		break;
 	default:
 		syslog(LOG_WARNING, "Unsupported command: 0x%04u", cmd);
 		err = "Unsupported command";

+ 1 - 0
klish/ktp_session.h

@@ -95,6 +95,7 @@ bool_t ktp_session_completion(ktp_session_t *ktp, const char *line,
 	bool_t dry_run);
 bool_t ktp_session_help(ktp_session_t *ktp, const char *line);
 bool_t ktp_session_stdin(ktp_session_t *ktp, const char *line, size_t line_len);
+bool_t ktp_session_stdout_close(ktp_session_t *ktp);
 bool_t ktp_session_retcode(ktp_session_t *ktp, int *retcode);
 ktp_status_e ktp_session_cmd_features(const ktp_session_t *ktp);