The branch main has been updated by rlibby:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=3e5e9939cda3b24df37c37da5f195415a894d9fd

commit 3e5e9939cda3b24df37c37da5f195415a894d9fd
Author:     Ryan Libby <rli...@freebsd.org>
AuthorDate: 2021-03-14 23:04:27 +0000
Commit:     Ryan Libby <rli...@freebsd.org>
CommitDate: 2021-03-14 23:04:27 +0000

    ddb: enable the use of ^C and ^S/^Q
    
    This lets one interrupt DDB's output, which is useful if paging is
    disabled and the output device is slow.
    
    This follows a previous implementation in svn r311952 / git
    5fddef79998678d256ba30316353393b4d8ebb32 which was reverted because it
    broke DDB type-ahead.
    
    Now, try this again, but with a 512-byte type-ahead buffer.  While there
    is buffer space, control input is handled and non-control input is
    buffered.  When the buffer is exhausted, the default is to print a
    warning and drop further non-control input in order to continue handling
    control input.  sysctl debug.ddb.prioritize_control_input can be set to
    0 to instead preserve all input but lose immediate handling of control
    input.  This could for example effect pasting of a large script into the
    ddb console.
    
    Suggested by:   Anton Rang <r...@acm.org>
    Reviewed by:    markj
    Discussed with: imp
    Sponsored by:   Dell EMC Isilon
    Differential Revision:  https://reviews.freebsd.org/D28676
---
 share/man/man4/ddb.4 |  15 +++++-
 sys/ddb/db_input.c   | 126 +++++++++++++++++++++++++++++++++++++++++----------
 sys/ddb/db_output.c  |   2 +-
 sys/ddb/ddb.h        |   1 +
 4 files changed, 119 insertions(+), 25 deletions(-)

diff --git a/share/man/man4/ddb.4 b/share/man/man4/ddb.4
index 1fe3490edd36..4f1614d8e006 100644
--- a/share/man/man4/ddb.4
+++ b/share/man/man4/ddb.4
@@ -26,7 +26,7 @@
 .\"
 .\" $FreeBSD$
 .\"
-.Dd January 26, 2021
+.Dd March 14, 2021
 .Dt DDB 4
 .Os
 .Sh NAME
@@ -1571,6 +1571,19 @@ The debugger may be entered by setting the
 .Xr sysctl 8
 .Va debug.kdb.enter
 to 1.
+.Pp
+Output may be interrupted, paused, and resumed with the control
+characters CTRL-C, CTRL-S, and CTRL-Q.
+Because these control characters are received as in-band data from the
+console, there is an input buffer, and once that buffer fills
+.Nm
+must either stop responding to control characters or drop additional
+input while continuing to search for control characters.
+This behavior is controlled by the tunable
+.Xr sysctl 8
+.Va debug.ddb.prioritize_control_input ,
+which defaults to 1.
+The input buffer size is 512 bytes.
 .Sh FILES
 Header files mentioned in this manual page can be found below
 .Pa /usr/include
diff --git a/sys/ddb/db_input.c b/sys/ddb/db_input.c
index 41396e0a041f..a7d06e17f5c1 100644
--- a/sys/ddb/db_input.c
+++ b/sys/ddb/db_input.c
@@ -36,6 +36,7 @@ __FBSDID("$FreeBSD$");
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/cons.h>
+#include <sys/sysctl.h>
 
 #include <ddb/ddb.h>
 #include <ddb/db_output.h>
@@ -54,6 +55,19 @@ static char *        db_lbuf_end;    /* end of input line 
buffer */
 static char *  db_lc;          /* current character */
 static char *  db_le;          /* one past last character */
 
+/*
+ * Raw input buffer, processed only for certain control characters.
+ */
+#define        DB_RAW_SIZE     512
+static char    db_raw[DB_RAW_SIZE];
+static u_int   db_raw_pos;
+static u_int   db_raw_cnt;
+static int     db_raw_warned;
+static int     ddb_prioritize_control_input = 1;
+SYSCTL_INT(_debug_ddb, OID_AUTO, prioritize_control_input, CTLFLAG_RWTUN,
+    &ddb_prioritize_control_input, 0,
+    "Drop input when the buffer fills in order to keep servicing ^C/^S/^Q");
+
 /*
  * Simple input line history support.
  */
@@ -65,11 +79,13 @@ static int  db_lhist_nlines;
 #define        BLANK           ' '
 #define        BACKUP          '\b'
 
-static int     cnmaygetc(void);
 static void    db_delete(int n, int bwd);
 static int     db_inputchar(int c);
 static void    db_putnchars(int c, int count);
 static void    db_putstring(char *s, int count);
+static int     db_raw_pop(void);
+static void    db_raw_push(int);
+static int     db_raw_space(void);
 
 static void
 db_putstring(s, count)
@@ -307,10 +323,50 @@ db_inputchar(c)
        return (0);
 }
 
+/* Get a character from the console, first checking the raw input buffer. */
+int
+db_getc(void)
+{
+       int c;
+
+       if (db_raw_cnt == 0) {
+               c = cngetc();
+       } else {
+               c = db_raw_pop();
+               if (c == '\r')
+                       c = '\n';
+       }
+       return (c);
+}
+
+/* Whether the raw input buffer has space to accept another character. */
 static int
-cnmaygetc()
+db_raw_space(void)
+{
+
+       return (db_raw_cnt < DB_RAW_SIZE);
+}
+
+/* Un-get a character from the console by buffering it. */
+static void
+db_raw_push(int c)
 {
-       return (-1);
+
+       if (!db_raw_space())
+               db_error(NULL);
+       db_raw[(db_raw_pos + db_raw_cnt++) % DB_RAW_SIZE] = c;
+}
+
+/* Drain a character from the raw input buffer. */
+static int
+db_raw_pop(void)
+{
+
+       if (db_raw_cnt == 0)
+               return (-1);
+       db_raw_cnt--;
+       db_raw_warned = 0;
+       return (db_raw[db_raw_pos++ % DB_RAW_SIZE]);
 }
 
 int
@@ -339,7 +395,7 @@ db_readline(lstart, lsize)
        db_lc = lstart;
        db_le = lstart;
 
-       while (!db_inputchar(cngetc()))
+       while (!db_inputchar(db_getc()))
            continue;
 
        db_capture_write(lstart, db_le - db_lbuf_start);
@@ -361,30 +417,54 @@ db_readline(lstart, lsize)
        return (db_le - db_lbuf_start);
 }
 
+static void
+db_do_interrupt(const char *reason)
+{
+
+       /* Do a pager quit too because some commands have jmpbuf handling. */
+       db_disable_pager();
+       db_pager_quit = 1;
+       db_error(reason);
+}
+
 void
 db_check_interrupt(void)
 {
        int     c;
 
-       c = cnmaygetc();
-       switch (c) {
-           case -1:            /* no character */
-               return;
-
-           case CTRL('c'):
-               db_error((char *)0);
-               /*NOTREACHED*/
-
-           case CTRL('s'):
-               do {
-                   c = cnmaygetc();
-                   if (c == CTRL('c'))
-                       db_error((char *)0);
-               } while (c != CTRL('q'));
-               break;
+       /*
+        * Check console input for control characters.  Non-control input is
+        * buffered.  When buffer space is exhausted, either stop responding to
+        * control input or drop further non-control input on the floor.
+        */
+       for (;;) {
+               if (!ddb_prioritize_control_input && !db_raw_space())
+                       return;
+               c = cncheckc();
+               switch (c) {
+               case -1:                /* no character */
+                       return;
+
+               case CTRL('c'):
+                       db_do_interrupt("^C");
+                       /*NOTREACHED*/
+
+               case CTRL('s'):
+                       do {
+                               c = cncheckc();
+                               if (c == CTRL('c'))
+                                       db_do_interrupt("^C");
+                       } while (c != CTRL('q'));
+                       break;
 
-           default:
-               /* drop on floor */
-               break;
+               default:
+                       if (db_raw_space()) {
+                               db_raw_push(c);
+                       } else if (!db_raw_warned) {
+                               db_raw_warned = 1;
+                               db_printf("\n--Exceeded input buffer--\n");
+                       }
+                       break;
+               }
        }
 }
diff --git a/sys/ddb/db_output.c b/sys/ddb/db_output.c
index 3517187f8206..41a8c7128359 100644
--- a/sys/ddb/db_output.c
+++ b/sys/ddb/db_output.c
@@ -260,7 +260,7 @@ db_pager(void)
        db_printf("--More--\r");
        done = 0;
        while (!done) {
-               c = cngetc();
+               c = db_getc();
                switch (c) {
                case 'e':
                case 'j':
diff --git a/sys/ddb/ddb.h b/sys/ddb/ddb.h
index 81448474c514..5ae48d21fda9 100644
--- a/sys/ddb/ddb.h
+++ b/sys/ddb/ddb.h
@@ -197,6 +197,7 @@ db_addr_t   db_disasm(db_addr_t loc, bool altfmt);
                                /* instruction disassembler */
 void           db_error(const char *s);
 int            db_expression(db_expr_t *valuep);
+int            db_getc(void);
 int            db_get_variable(db_expr_t *valuep);
 void           db_iprintf(const char *,...) __printflike(1, 2);
 struct proc    *db_lookup_proc(db_expr_t addr);
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to