linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/5] kdb: Cleanup code to read user input and handle escape sequences
@ 2019-10-14 15:46 Daniel Thompson
  2019-10-14 15:46 ` [PATCH v3 1/5] kdb: Tidy up code to " Daniel Thompson
                   ` (4 more replies)
  0 siblings, 5 replies; 10+ messages in thread
From: Daniel Thompson @ 2019-10-14 15:46 UTC (permalink / raw)
  To: Jason Wessel, Douglas Anderson
  Cc: Daniel Thompson, kgdb-bugreport, linux-kernel, patches

I've been meaning to repost this for some time, and inspired by
having someone keen to review it, I dug it out again!

I split this as carefully as I could into small pieces but the original
code was complex so even in small bits it doesn't make for light
reading.  Things do make more sense once you realize/remember that
escape_delay is a count down timer that expires the escape sequences!

Most of the patches are simple tidy ups although patches 4 and 5
introduce new behaviours. Patch 4 shouldn't be controversial but
perhaps patch 5 is (although hopefully not ;-) ).

Mostly this is auto tested, see here:
https://github.com/daniel-thompson/kgdbtest/commit/c65e28d99357c2df6dac2cebe195574e634d04dc

Changes in v3:

 - Accepted all review comments from Doug (except the return type
   of kdb_getchar() as discussed in the mail threads). In particular
   this fixes a bug in the handling of the btaprompt.
 - Added Doug's reviewed-by to patches 1 and 2.

Changes in v2:

 - Improve comment in patch 4 to better describe what is happening
 - Rebase on v5.4-rc2

Daniel Thompson (5):
  kdb: Tidy up code to handle escape sequences
  kdb: Simplify code to fetch characters from console
  kdb: Remove special case logic from kdb_read()
  kdb: Improve handling of characters from different input sources
  kdb: Tweak escape handling for vi users

 kernel/debug/kdb/kdb_bt.c      |  22 ++--
 kernel/debug/kdb/kdb_io.c      | 229 ++++++++++++++++-----------------
 kernel/debug/kdb/kdb_private.h |   1 +
 3 files changed, 123 insertions(+), 129 deletions(-)

--
2.21.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH v3 1/5] kdb: Tidy up code to handle escape sequences
  2019-10-14 15:46 [PATCH v3 0/5] kdb: Cleanup code to read user input and handle escape sequences Daniel Thompson
@ 2019-10-14 15:46 ` Daniel Thompson
  2019-10-14 15:46 ` [PATCH v3 2/5] kdb: Simplify code to fetch characters from console Daniel Thompson
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Daniel Thompson @ 2019-10-14 15:46 UTC (permalink / raw)
  To: Jason Wessel, Douglas Anderson
  Cc: Daniel Thompson, kgdb-bugreport, linux-kernel, patches

kdb_read_get_key() has extremely complex break/continue control flow
managed by state variables and is very hard to review or modify. In
particular the way the escape sequence handling interacts with the
general control flow is hard to follow. Separate out the escape key
handling, without changing the control flow. This makes the main body of
the code easier to review.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 kernel/debug/kdb/kdb_io.c | 127 ++++++++++++++++++++------------------
 1 file changed, 66 insertions(+), 61 deletions(-)

diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index 3a5184eb6977..68e2c29f14f5 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -49,6 +49,63 @@ static int kgdb_transition_check(char *buffer)
 	return 0;
 }
 
+/*
+ * kdb_read_handle_escape
+ *
+ * Run a validity check on an accumulated escape sequence.
+ *
+ * Returns -1 if the escape sequence is unwanted, 0 if it is incomplete,
+ * otherwise it returns a mapped key value to pass to the upper layers.
+ */
+static int kdb_read_handle_escape(char *buf, size_t sz)
+{
+	char *lastkey = buf + sz - 1;
+
+	switch (sz) {
+	case 1:
+		if (*lastkey == '\e')
+			return 0;
+		break;
+
+	case 2: /* \e<something> */
+		if (*lastkey == '[')
+			return 0;
+		break;
+
+	case 3:
+		switch (*lastkey) {
+		case 'A': /* \e[A, up arrow */
+			return 16;
+		case 'B': /* \e[B, down arrow */
+			return 14;
+		case 'C': /* \e[C, right arrow */
+			return 6;
+		case 'D': /* \e[D, left arrow */
+			return 2;
+		case '1': /* \e[<1,3,4>], may be home, del, end */
+		case '3':
+		case '4':
+			return 0;
+		}
+		break;
+
+	case 4:
+		if (*lastkey == '~') {
+			switch (buf[2]) {
+			case '1': /* \e[1~, home */
+				return 1;
+			case '3': /* \e[3~, del */
+				return 4;
+			case '4': /* \e[4~, end */
+				return 5;
+			}
+		}
+		break;
+	}
+
+	return -1;
+}
+
 static int kdb_read_get_key(char *buffer, size_t bufsize)
 {
 #define ESCAPE_UDELAY 1000
@@ -102,68 +159,16 @@ static int kdb_read_get_key(char *buffer, size_t bufsize)
 				escape_delay = 2;
 				continue;
 			}
-			if (ped - escape_data == 1) {
-				/* \e */
-				continue;
-			} else if (ped - escape_data == 2) {
-				/* \e<something> */
-				if (key != '[')
-					escape_delay = 2;
-				continue;
-			} else if (ped - escape_data == 3) {
-				/* \e[<something> */
-				int mapkey = 0;
-				switch (key) {
-				case 'A': /* \e[A, up arrow */
-					mapkey = 16;
-					break;
-				case 'B': /* \e[B, down arrow */
-					mapkey = 14;
-					break;
-				case 'C': /* \e[C, right arrow */
-					mapkey = 6;
-					break;
-				case 'D': /* \e[D, left arrow */
-					mapkey = 2;
-					break;
-				case '1': /* dropthrough */
-				case '3': /* dropthrough */
-				/* \e[<1,3,4>], may be home, del, end */
-				case '4':
-					mapkey = -1;
-					break;
-				}
-				if (mapkey != -1) {
-					if (mapkey > 0) {
-						escape_data[0] = mapkey;
-						escape_data[1] = '\0';
-					}
-					escape_delay = 2;
-				}
-				continue;
-			} else if (ped - escape_data == 4) {
-				/* \e[<1,3,4><something> */
-				int mapkey = 0;
-				if (key == '~') {
-					switch (escape_data[2]) {
-					case '1': /* \e[1~, home */
-						mapkey = 1;
-						break;
-					case '3': /* \e[3~, del */
-						mapkey = 4;
-						break;
-					case '4': /* \e[4~, end */
-						mapkey = 5;
-						break;
-					}
-				}
-				if (mapkey > 0) {
-					escape_data[0] = mapkey;
-					escape_data[1] = '\0';
-				}
-				escape_delay = 2;
-				continue;
+
+			key = kdb_read_handle_escape(escape_data,
+						     ped - escape_data);
+			if (key > 0) {
+				escape_data[0] = key;
+				escape_data[1] = '\0';
 			}
+			if (key)
+				escape_delay = 2;
+			continue;
 		}
 		break;	/* A key to process */
 	}
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 2/5] kdb: Simplify code to fetch characters from console
  2019-10-14 15:46 [PATCH v3 0/5] kdb: Cleanup code to read user input and handle escape sequences Daniel Thompson
  2019-10-14 15:46 ` [PATCH v3 1/5] kdb: Tidy up code to " Daniel Thompson
@ 2019-10-14 15:46 ` Daniel Thompson
  2019-10-14 15:46 ` [PATCH v3 3/5] kdb: Remove special case logic from kdb_read() Daniel Thompson
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 10+ messages in thread
From: Daniel Thompson @ 2019-10-14 15:46 UTC (permalink / raw)
  To: Jason Wessel, Douglas Anderson
  Cc: Daniel Thompson, kgdb-bugreport, linux-kernel, patches

Currently kdb_read_get_key() contains complex control flow that, on
close inspection, turns out to be unnecessary. In particular:

1. It is impossible to enter the branch conditioned on (escape_delay == 1)
   except when the loop enters with (escape_delay == 2) allowing us to
   combine the branches.

2. Most of the code conditioned on (escape_delay == 2) simply modifies
   local data and then breaks out of the loop causing the function to
   return escape_data[0].

3. Based on #2 there is not actually any need to ever explicitly set
   escape_delay to 2 because we it is much simpler to directly return
   escape_data[0] instead.

4. escape_data[0] is, for all but one exit path, known to be '\e'.

Simplify the code based on these observations.

There is a subtle (and harmless) change of behaviour resulting from this
simplification: instead of letting the escape timeout after ~1998
milliseconds we now timeout after ~2000 milliseconds

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
Reviewed-by: Douglas Anderson <dianders@chromium.org>
---
 kernel/debug/kdb/kdb_io.c | 38 ++++++++++++++------------------------
 1 file changed, 14 insertions(+), 24 deletions(-)

diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index 68e2c29f14f5..78cb6e339408 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -122,25 +122,18 @@ static int kdb_read_get_key(char *buffer, size_t bufsize)
 			touch_nmi_watchdog();
 			f = &kdb_poll_funcs[0];
 		}
-		if (escape_delay == 2) {
-			*ped = '\0';
-			ped = escape_data;
-			--escape_delay;
-		}
-		if (escape_delay == 1) {
-			key = *ped++;
-			if (!*ped)
-				--escape_delay;
-			break;
-		}
+
 		key = (*f)();
+
 		if (key == -1) {
 			if (escape_delay) {
 				udelay(ESCAPE_UDELAY);
-				--escape_delay;
+				if (--escape_delay == 0)
+					return '\e';
 			}
 			continue;
 		}
+
 		if (bufsize <= 2) {
 			if (key == '\r')
 				key = '\n';
@@ -148,28 +141,25 @@ static int kdb_read_get_key(char *buffer, size_t bufsize)
 			*buffer = '\0';
 			return -1;
 		}
+
 		if (escape_delay == 0 && key == '\e') {
 			escape_delay = ESCAPE_DELAY;
 			ped = escape_data;
 			f_escape = f;
 		}
 		if (escape_delay) {
-			*ped++ = key;
-			if (f_escape != f) {
-				escape_delay = 2;
-				continue;
-			}
+			if (f_escape != f)
+				return '\e';
 
+			*ped++ = key;
 			key = kdb_read_handle_escape(escape_data,
 						     ped - escape_data);
-			if (key > 0) {
-				escape_data[0] = key;
-				escape_data[1] = '\0';
-			}
-			if (key)
-				escape_delay = 2;
-			continue;
+			if (key < 0)
+				return '\e';
+			if (key == 0)
+				continue;
 		}
+
 		break;	/* A key to process */
 	}
 	return key;
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 3/5] kdb: Remove special case logic from kdb_read()
  2019-10-14 15:46 [PATCH v3 0/5] kdb: Cleanup code to read user input and handle escape sequences Daniel Thompson
  2019-10-14 15:46 ` [PATCH v3 1/5] kdb: Tidy up code to " Daniel Thompson
  2019-10-14 15:46 ` [PATCH v3 2/5] kdb: Simplify code to fetch characters from console Daniel Thompson
@ 2019-10-14 15:46 ` Daniel Thompson
  2019-10-17  4:10   ` Doug Anderson
  2019-10-14 15:46 ` [PATCH v3 4/5] kdb: Improve handling of characters from different input sources Daniel Thompson
  2019-10-14 15:46 ` [PATCH v3 5/5] kdb: Tweak escape handling for vi users Daniel Thompson
  4 siblings, 1 reply; 10+ messages in thread
From: Daniel Thompson @ 2019-10-14 15:46 UTC (permalink / raw)
  To: Jason Wessel, Douglas Anderson
  Cc: Daniel Thompson, kgdb-bugreport, linux-kernel, patches

kdb_read() contains special case logic to force it exit after reading
a single character. We can remove all the special case logic by directly
calling the function to read a single character instead. This also
allows us to tidy up the function prototype which, because it now matches
getchar(), we can also rename in order to make its role clearer.

This does involve some extra code to handle btaprompt properly but we
don't mind the new lines of code here because the old code had some
interesting problems (bad newline handling, treating unexpected
characters like <cr>).

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
---
 kernel/debug/kdb/kdb_bt.c      | 22 +++++++----
 kernel/debug/kdb/kdb_io.c      | 67 +++++++++++++++-------------------
 kernel/debug/kdb/kdb_private.h |  1 +
 3 files changed, 45 insertions(+), 45 deletions(-)

diff --git a/kernel/debug/kdb/kdb_bt.c b/kernel/debug/kdb/kdb_bt.c
index 7e2379aa0a1e..b6dc4d7470fd 100644
--- a/kernel/debug/kdb/kdb_bt.c
+++ b/kernel/debug/kdb/kdb_bt.c
@@ -81,9 +81,10 @@ static int
 kdb_bt1(struct task_struct *p, unsigned long mask,
 	int argcount, int btaprompt)
 {
-	char buffer[2];
-	if (kdb_getarea(buffer[0], (unsigned long)p) ||
-	    kdb_getarea(buffer[0], (unsigned long)(p+1)-1))
+	char ch;
+
+	if (kdb_getarea(ch, (unsigned long)p) ||
+	    kdb_getarea(ch, (unsigned long)(p+1)-1))
 		return KDB_BADADDR;
 	if (!kdb_task_state(p, mask))
 		return 0;
@@ -91,12 +92,17 @@ kdb_bt1(struct task_struct *p, unsigned long mask,
 	kdb_ps1(p);
 	kdb_show_stack(p, NULL);
 	if (btaprompt) {
-		kdb_getstr(buffer, sizeof(buffer),
-			   "Enter <q> to end, <cr> to continue:");
-		if (buffer[0] == 'q') {
-			kdb_printf("\n");
+		kdb_printf("Enter <q> to end, <cr> or <space> to continue:");
+		ch = kdb_getchar();
+		while (!strchr("\r\n q", ch))
+			ch = kdb_getchar();
+		kdb_printf("\n");
+
+		/* reset the pager */
+		kdb_nextline = 1;
+
+		if (ch == 'q')
 			return 1;
-		}
 	}
 	touch_nmi_watchdog();
 	return 0;
diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index 78cb6e339408..39476616295e 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -50,14 +50,14 @@ static int kgdb_transition_check(char *buffer)
 }
 
 /*
- * kdb_read_handle_escape
+ * kdb_handle_escape
  *
  * Run a validity check on an accumulated escape sequence.
  *
  * Returns -1 if the escape sequence is unwanted, 0 if it is incomplete,
  * otherwise it returns a mapped key value to pass to the upper layers.
  */
-static int kdb_read_handle_escape(char *buf, size_t sz)
+static int kdb_handle_escape(char *buf, size_t sz)
 {
 	char *lastkey = buf + sz - 1;
 
@@ -106,7 +106,22 @@ static int kdb_read_handle_escape(char *buf, size_t sz)
 	return -1;
 }
 
-static int kdb_read_get_key(char *buffer, size_t bufsize)
+/**
+ * kdb_getchar() - Read a single character from a kdb console (or consoles).
+ *
+ * Other than polling the various consoles that are currently enabled,
+ * most of the work done in this function is dealing with escape sequences.
+ *
+ * An escape key could be the start of a vt100 control sequence such as \e[D
+ * (left arrow) or it could be a character in its own right.  The standard
+ * method for detecting the difference is to wait for 2 seconds to see if there
+ * are any other characters.  kdb is complicated by the lack of a timer service
+ * (interrupts are off), by multiple input sources. Escape sequence processing
+ * has to be done as states in the polling loop.
+ *
+ * Return: The key pressed or a control code derived from an escape sequence.
+ */
+char kdb_getchar(void)
 {
 #define ESCAPE_UDELAY 1000
 #define ESCAPE_DELAY (2*1000000/ESCAPE_UDELAY) /* 2 seconds worth of udelays */
@@ -124,7 +139,6 @@ static int kdb_read_get_key(char *buffer, size_t bufsize)
 		}
 
 		key = (*f)();
-
 		if (key == -1) {
 			if (escape_delay) {
 				udelay(ESCAPE_UDELAY);
@@ -134,14 +148,6 @@ static int kdb_read_get_key(char *buffer, size_t bufsize)
 			continue;
 		}
 
-		if (bufsize <= 2) {
-			if (key == '\r')
-				key = '\n';
-			*buffer++ = key;
-			*buffer = '\0';
-			return -1;
-		}
-
 		if (escape_delay == 0 && key == '\e') {
 			escape_delay = ESCAPE_DELAY;
 			ped = escape_data;
@@ -152,7 +158,7 @@ static int kdb_read_get_key(char *buffer, size_t bufsize)
 				return '\e';
 
 			*ped++ = key;
-			key = kdb_read_handle_escape(escape_data,
+			key = kdb_handle_escape(escape_data,
 						     ped - escape_data);
 			if (key < 0)
 				return '\e';
@@ -183,17 +189,7 @@ static int kdb_read_get_key(char *buffer, size_t bufsize)
  *	function.  It is not reentrant - it relies on the fact
  *	that while kdb is running on only one "master debug" cpu.
  * Remarks:
- *
- * The buffer size must be >= 2.  A buffer size of 2 means that the caller only
- * wants a single key.
- *
- * An escape key could be the start of a vt100 control sequence such as \e[D
- * (left arrow) or it could be a character in its own right.  The standard
- * method for detecting the difference is to wait for 2 seconds to see if there
- * are any other characters.  kdb is complicated by the lack of a timer service
- * (interrupts are off), by multiple input sources and by the need to sometimes
- * return after just one key.  Escape sequence processing has to be done as
- * states in the polling loop.
+ *	The buffer size must be >= 2.
  */
 
 static char *kdb_read(char *buffer, size_t bufsize)
@@ -228,9 +224,7 @@ static char *kdb_read(char *buffer, size_t bufsize)
 	*cp = '\0';
 	kdb_printf("%s", buffer);
 poll_again:
-	key = kdb_read_get_key(buffer, bufsize);
-	if (key == -1)
-		return buffer;
+	key = kdb_getchar();
 	if (key != 9)
 		tab = 0;
 	switch (key) {
@@ -741,7 +735,7 @@ int vkdb_printf(enum kdb_msgsrc src, const char *fmt, va_list ap)
 
 	/* check for having reached the LINES number of printed lines */
 	if (kdb_nextline >= linecount) {
-		char buf1[16] = "";
+		char ch;
 
 		/* Watch out for recursion here.  Any routine that calls
 		 * kdb_printf will come back through here.  And kdb_read
@@ -776,39 +770,38 @@ int vkdb_printf(enum kdb_msgsrc src, const char *fmt, va_list ap)
 		if (logging)
 			printk("%s", moreprompt);
 
-		kdb_read(buf1, 2); /* '2' indicates to return
-				    * immediately after getting one key. */
+		ch = kdb_getchar();
 		kdb_nextline = 1;	/* Really set output line 1 */
 
 		/* empty and reset the buffer: */
 		kdb_buffer[0] = '\0';
 		next_avail = kdb_buffer;
 		size_avail = sizeof(kdb_buffer);
-		if ((buf1[0] == 'q') || (buf1[0] == 'Q')) {
+		if ((ch == 'q') || (ch == 'Q')) {
 			/* user hit q or Q */
 			KDB_FLAG_SET(CMD_INTERRUPT); /* command interrupted */
 			KDB_STATE_CLEAR(PAGER);
 			/* end of command output; back to normal mode */
 			kdb_grepping_flag = 0;
 			kdb_printf("\n");
-		} else if (buf1[0] == ' ') {
+		} else if (ch == ' ') {
 			kdb_printf("\r");
 			suspend_grep = 1; /* for this recursion */
-		} else if (buf1[0] == '\n') {
+		} else if (ch == '\n' || ch == '\r') {
 			kdb_nextline = linecount - 1;
 			kdb_printf("\r");
 			suspend_grep = 1; /* for this recursion */
-		} else if (buf1[0] == '/' && !kdb_grepping_flag) {
+		} else if (ch == '/' && !kdb_grepping_flag) {
 			kdb_printf("\r");
 			kdb_getstr(kdb_grep_string, KDB_GREP_STRLEN,
 				   kdbgetenv("SEARCHPROMPT") ?: "search> ");
 			*strchrnul(kdb_grep_string, '\n') = '\0';
 			kdb_grepping_flag += KDB_GREPPING_FLAG_SEARCH;
 			suspend_grep = 1; /* for this recursion */
-		} else if (buf1[0] && buf1[0] != '\n') {
-			/* user hit something other than enter */
+		} else if (ch) {
+			/* user hit something unexpected */
 			suspend_grep = 1; /* for this recursion */
-			if (buf1[0] != '/')
+			if (ch != '/')
 				kdb_printf(
 				    "\nOnly 'q', 'Q' or '/' are processed at "
 				    "more prompt, input ignored\n");
diff --git a/kernel/debug/kdb/kdb_private.h b/kernel/debug/kdb/kdb_private.h
index 2118d8258b7c..55d052061ef9 100644
--- a/kernel/debug/kdb/kdb_private.h
+++ b/kernel/debug/kdb/kdb_private.h
@@ -210,6 +210,7 @@ extern void kdb_ps1(const struct task_struct *p);
 extern void kdb_print_nameval(const char *name, unsigned long val);
 extern void kdb_send_sig(struct task_struct *p, int sig);
 extern void kdb_meminfo_proc_show(void);
+extern char kdb_getchar(void);
 extern char *kdb_getstr(char *, size_t, const char *);
 extern void kdb_gdb_state_pass(char *buf);
 
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 4/5] kdb: Improve handling of characters from different input sources
  2019-10-14 15:46 [PATCH v3 0/5] kdb: Cleanup code to read user input and handle escape sequences Daniel Thompson
                   ` (2 preceding siblings ...)
  2019-10-14 15:46 ` [PATCH v3 3/5] kdb: Remove special case logic from kdb_read() Daniel Thompson
@ 2019-10-14 15:46 ` Daniel Thompson
  2019-10-17  4:11   ` Doug Anderson
  2019-10-14 15:46 ` [PATCH v3 5/5] kdb: Tweak escape handling for vi users Daniel Thompson
  4 siblings, 1 reply; 10+ messages in thread
From: Daniel Thompson @ 2019-10-14 15:46 UTC (permalink / raw)
  To: Jason Wessel, Douglas Anderson
  Cc: Daniel Thompson, kgdb-bugreport, linux-kernel, patches

Currently if an escape timer is interrupted by a character from a
different input source then the new character is discarded and the
function returns '\e' (which will be discarded by the level above).
It is hard to see why this would ever be the desired behaviour.
Fix this to return the new character rather than the '\e'.

This is a bigger refactor than might be expected because the new
character needs to go through escape sequence detection.

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
---
 kernel/debug/kdb/kdb_io.c | 39 +++++++++++++++++++--------------------
 1 file changed, 19 insertions(+), 20 deletions(-)

diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index 39476616295e..f9839566c7d6 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -125,10 +125,10 @@ char kdb_getchar(void)
 {
 #define ESCAPE_UDELAY 1000
 #define ESCAPE_DELAY (2*1000000/ESCAPE_UDELAY) /* 2 seconds worth of udelays */
-	char escape_data[5];	/* longest vt100 escape sequence is 4 bytes */
-	char *ped = escape_data;
+	char buf[4];	/* longest vt100 escape sequence is 4 bytes */
+	char *pbuf = buf;
 	int escape_delay = 0;
-	get_char_func *f, *f_escape = NULL;
+	get_char_func *f, *f_prev = NULL;
 	int key;
 
 	for (f = &kdb_poll_funcs[0]; ; ++f) {
@@ -148,27 +148,26 @@ char kdb_getchar(void)
 			continue;
 		}
 
-		if (escape_delay == 0 && key == '\e') {
+		/*
+		 * When the first character is received (or we get a change
+		 * input source) we set ourselves up to handle an escape
+		 * sequences (just in case).
+		 */
+		if (f_prev != f) {
+			f_prev = f;
+			pbuf = buf;
 			escape_delay = ESCAPE_DELAY;
-			ped = escape_data;
-			f_escape = f;
-		}
-		if (escape_delay) {
-			if (f_escape != f)
-				return '\e';
-
-			*ped++ = key;
-			key = kdb_handle_escape(escape_data,
-						     ped - escape_data);
-			if (key < 0)
-				return '\e';
-			if (key == 0)
-				continue;
 		}
 
-		break;	/* A key to process */
+		*pbuf++ = key;
+		key = kdb_handle_escape(buf, pbuf - buf);
+		if (key < 0) /* no escape sequence; return first character */
+			return buf[0];
+		if (key > 0)
+			return key;
 	}
-	return key;
+
+	unreachable();
 }
 
 /*
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH v3 5/5] kdb: Tweak escape handling for vi users
  2019-10-14 15:46 [PATCH v3 0/5] kdb: Cleanup code to read user input and handle escape sequences Daniel Thompson
                   ` (3 preceding siblings ...)
  2019-10-14 15:46 ` [PATCH v3 4/5] kdb: Improve handling of characters from different input sources Daniel Thompson
@ 2019-10-14 15:46 ` Daniel Thompson
  2019-10-17  4:12   ` Doug Anderson
  4 siblings, 1 reply; 10+ messages in thread
From: Daniel Thompson @ 2019-10-14 15:46 UTC (permalink / raw)
  To: Jason Wessel, Douglas Anderson
  Cc: Daniel Thompson, kgdb-bugreport, linux-kernel, patches

Currently if sequences such as "\ehelp\r" are delivered to the console then
the h gets eaten by the escape handling code. Since pressing escape
becomes something of a nervous twitch for vi users (and that escape doesn't
have much effect at a shell prompt) it is more helpful to emit the 'h' than
the '\e'.

We don't simply choose to emit the final character for all escape sequences
since that will do odd things for unsupported escape sequences (in
other words we retain the existing behaviour once we see '\e[').

Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
---
 kernel/debug/kdb/kdb_io.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/kernel/debug/kdb/kdb_io.c b/kernel/debug/kdb/kdb_io.c
index f9839566c7d6..5e71bb2596ed 100644
--- a/kernel/debug/kdb/kdb_io.c
+++ b/kernel/debug/kdb/kdb_io.c
@@ -161,8 +161,8 @@ char kdb_getchar(void)
 
 		*pbuf++ = key;
 		key = kdb_handle_escape(buf, pbuf - buf);
-		if (key < 0) /* no escape sequence; return first character */
-			return buf[0];
+		if (key < 0) /* no escape sequence; return best character */
+			return buf[pbuf - buf == 2 ? 1 : 0];
 		if (key > 0)
 			return key;
 	}
-- 
2.21.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 3/5] kdb: Remove special case logic from kdb_read()
  2019-10-14 15:46 ` [PATCH v3 3/5] kdb: Remove special case logic from kdb_read() Daniel Thompson
@ 2019-10-17  4:10   ` Doug Anderson
  2019-10-17  9:14     ` Daniel Thompson
  0 siblings, 1 reply; 10+ messages in thread
From: Doug Anderson @ 2019-10-17  4:10 UTC (permalink / raw)
  To: Daniel Thompson; +Cc: Jason Wessel, kgdb-bugreport, LKML, Patch Tracking

Hi,

On Mon, Oct 14, 2019 at 8:46 AM Daniel Thompson
<daniel.thompson@linaro.org> wrote:
>
> @@ -91,12 +92,17 @@ kdb_bt1(struct task_struct *p, unsigned long mask,
>         kdb_ps1(p);
>         kdb_show_stack(p, NULL);
>         if (btaprompt) {
> -               kdb_getstr(buffer, sizeof(buffer),
> -                          "Enter <q> to end, <cr> to continue:");
> -               if (buffer[0] == 'q') {
> -                       kdb_printf("\n");
> +               kdb_printf("Enter <q> to end, <cr> or <space> to continue:");
> +               ch = kdb_getchar();
> +               while (!strchr("\r\n q", ch))
> +                       ch = kdb_getchar();

nit: above 3 lines would be better with "do while", AKA:

do {
  ch = kdb_getchar();
} while (!strchr("\r\n q", ch));


> @@ -50,14 +50,14 @@ static int kgdb_transition_check(char *buffer)
>  }
>
>  /*
> - * kdb_read_handle_escape
> + * kdb_handle_escape

Optional nit: while you're touching this comment, you could make it
kerneldoc complaint.


> @@ -152,7 +158,7 @@ static int kdb_read_get_key(char *buffer, size_t bufsize)
>                                 return '\e';
>
>                         *ped++ = key;
> -                       key = kdb_read_handle_escape(escape_data,
> +                       key = kdb_handle_escape(escape_data,
>                                                      ped - escape_data);

nit: indentation no longer lines up for the "ped - escape_data" line.

Nothing here is terribly important, thus:

Reviewed-by: Douglas Anderson <dianders@chromium.org>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 4/5] kdb: Improve handling of characters from different input sources
  2019-10-14 15:46 ` [PATCH v3 4/5] kdb: Improve handling of characters from different input sources Daniel Thompson
@ 2019-10-17  4:11   ` Doug Anderson
  0 siblings, 0 replies; 10+ messages in thread
From: Doug Anderson @ 2019-10-17  4:11 UTC (permalink / raw)
  To: Daniel Thompson; +Cc: Jason Wessel, kgdb-bugreport, LKML, Patch Tracking

Hi,

On Mon, Oct 14, 2019 at 8:46 AM Daniel Thompson
<daniel.thompson@linaro.org> wrote:
>
> Currently if an escape timer is interrupted by a character from a
> different input source then the new character is discarded and the
> function returns '\e' (which will be discarded by the level above).
> It is hard to see why this would ever be the desired behaviour.
> Fix this to return the new character rather than the '\e'.
>
> This is a bigger refactor than might be expected because the new
> character needs to go through escape sequence detection.
>
> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
> ---
>  kernel/debug/kdb/kdb_io.c | 39 +++++++++++++++++++--------------------
>  1 file changed, 19 insertions(+), 20 deletions(-)

Reviewed-by: Douglas Anderson <dianders@chromium.org>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 5/5] kdb: Tweak escape handling for vi users
  2019-10-14 15:46 ` [PATCH v3 5/5] kdb: Tweak escape handling for vi users Daniel Thompson
@ 2019-10-17  4:12   ` Doug Anderson
  0 siblings, 0 replies; 10+ messages in thread
From: Doug Anderson @ 2019-10-17  4:12 UTC (permalink / raw)
  To: Daniel Thompson; +Cc: Jason Wessel, kgdb-bugreport, LKML, Patch Tracking

Hi,

On Mon, Oct 14, 2019 at 8:46 AM Daniel Thompson
<daniel.thompson@linaro.org> wrote:
>
> Currently if sequences such as "\ehelp\r" are delivered to the console then
> the h gets eaten by the escape handling code. Since pressing escape
> becomes something of a nervous twitch for vi users (and that escape doesn't
> have much effect at a shell prompt) it is more helpful to emit the 'h' than
> the '\e'.
>
> We don't simply choose to emit the final character for all escape sequences
> since that will do odd things for unsupported escape sequences (in
> other words we retain the existing behaviour once we see '\e[').
>
> Signed-off-by: Daniel Thompson <daniel.thompson@linaro.org>
> ---
>  kernel/debug/kdb/kdb_io.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)

Reviewed-by: Douglas Anderson <dianders@chromium.org>

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH v3 3/5] kdb: Remove special case logic from kdb_read()
  2019-10-17  4:10   ` Doug Anderson
@ 2019-10-17  9:14     ` Daniel Thompson
  0 siblings, 0 replies; 10+ messages in thread
From: Daniel Thompson @ 2019-10-17  9:14 UTC (permalink / raw)
  To: Doug Anderson; +Cc: Jason Wessel, kgdb-bugreport, LKML, Patch Tracking

On Wed, Oct 16, 2019 at 09:10:22PM -0700, Doug Anderson wrote:
> Hi,
> 
> On Mon, Oct 14, 2019 at 8:46 AM Daniel Thompson
> <daniel.thompson@linaro.org> wrote:
> >
> > @@ -91,12 +92,17 @@ kdb_bt1(struct task_struct *p, unsigned long mask,
> >         kdb_ps1(p);
> >         kdb_show_stack(p, NULL);
> >         if (btaprompt) {
> > -               kdb_getstr(buffer, sizeof(buffer),
> > -                          "Enter <q> to end, <cr> to continue:");
> > -               if (buffer[0] == 'q') {
> > -                       kdb_printf("\n");
> > +               kdb_printf("Enter <q> to end, <cr> or <space> to continue:");
> > +               ch = kdb_getchar();
> > +               while (!strchr("\r\n q", ch))
> > +                       ch = kdb_getchar();
> 
> nit: above 3 lines would be better with "do while", AKA:
> 
> do {
>   ch = kdb_getchar();
> } while (!strchr("\r\n q", ch));

Doh! Too much python...
> 
> 
> > @@ -50,14 +50,14 @@ static int kgdb_transition_check(char *buffer)
> >  }
> >
> >  /*
> > - * kdb_read_handle_escape
> > + * kdb_handle_escape
> 
> Optional nit: while you're touching this comment, you could make it
> kerneldoc complaint.
> 
> 
> > @@ -152,7 +158,7 @@ static int kdb_read_get_key(char *buffer, size_t bufsize)
> >                                 return '\e';
> >
> >                         *ped++ = key;
> > -                       key = kdb_read_handle_escape(escape_data,
> > +                       key = kdb_handle_escape(escape_data,
> >                                                      ped - escape_data);
> 
> nit: indentation no longer lines up for the "ped - escape_data" line.
> 
> Nothing here is terribly important, thus:
> 
> Reviewed-by: Douglas Anderson <dianders@chromium.org>

Thanks. I'll pick the nits (although I might leave v4 out for review
for a relatively short time before applying it ;-) ).


Daniel.

^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2019-10-17  9:14 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2019-10-14 15:46 [PATCH v3 0/5] kdb: Cleanup code to read user input and handle escape sequences Daniel Thompson
2019-10-14 15:46 ` [PATCH v3 1/5] kdb: Tidy up code to " Daniel Thompson
2019-10-14 15:46 ` [PATCH v3 2/5] kdb: Simplify code to fetch characters from console Daniel Thompson
2019-10-14 15:46 ` [PATCH v3 3/5] kdb: Remove special case logic from kdb_read() Daniel Thompson
2019-10-17  4:10   ` Doug Anderson
2019-10-17  9:14     ` Daniel Thompson
2019-10-14 15:46 ` [PATCH v3 4/5] kdb: Improve handling of characters from different input sources Daniel Thompson
2019-10-17  4:11   ` Doug Anderson
2019-10-14 15:46 ` [PATCH v3 5/5] kdb: Tweak escape handling for vi users Daniel Thompson
2019-10-17  4:12   ` Doug Anderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).