Use a new message buffer `consmsgbuf' to forward messages to a
TIOCCONS console (e.g. xconsole) via a timeout routine instead of calling into the tty code directly from printf(). This fixes a number of cases where calling printf() at the wrong time (such as with locks held) would cause a panic if xconsole is running. The TIOCCONS message buffer is 8k in size by default, but this can be changed with the kern.consmsgbuf_size sysctl. By default, messages are checked for 5 times per second. The timer runs and the buffer memory remains allocated only at times when a TIOCCONS console is active. Discussed on: freebsd-arch
This commit is contained in:
parent
7ca33ad1e8
commit
d29bf12ff8
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=116663
@ -89,9 +89,6 @@ struct snprintf_arg {
|
||||
|
||||
extern int log_open;
|
||||
|
||||
struct tty *constty; /* pointer to console "window" tty */
|
||||
|
||||
static void (*v_putc)(int) = cnputc; /* routine to putc on virtual console */
|
||||
static void msglogchar(int c, int pri);
|
||||
static void putchar(int ch, void *arg);
|
||||
static char *ksprintn(char *nbuf, uintmax_t num, int base, int *len);
|
||||
@ -335,21 +332,24 @@ static void
|
||||
putchar(int c, void *arg)
|
||||
{
|
||||
struct putchar_arg *ap = (struct putchar_arg*) arg;
|
||||
int flags = ap->flags;
|
||||
struct tty *tp = ap->tty;
|
||||
int consdirect, flags = ap->flags;
|
||||
|
||||
consdirect = ((flags & TOCONS) && constty == NULL);
|
||||
/* Don't use the tty code after a panic. */
|
||||
if (panicstr)
|
||||
constty = NULL;
|
||||
if ((flags & TOCONS) && tp == NULL && constty) {
|
||||
tp = constty;
|
||||
flags |= TOTTY;
|
||||
consdirect = 1;
|
||||
if (consdirect) {
|
||||
if (c != '\0')
|
||||
cnputc(c);
|
||||
} else {
|
||||
if ((flags & TOTTY) && tp != NULL)
|
||||
tputchar(c, tp);
|
||||
if ((flags & TOCONS) && constty != NULL)
|
||||
msgbuf_addchar(&consmsgbuf, c);
|
||||
}
|
||||
if ((flags & TOTTY) && tp && tputchar(c, tp) < 0 &&
|
||||
(flags & TOCONS) && tp == constty)
|
||||
constty = NULL;
|
||||
if ((flags & TOLOG))
|
||||
msglogchar(c, ap->pri);
|
||||
if ((flags & TOCONS) && constty == NULL && c != '\0')
|
||||
(*v_putc)(c);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -261,7 +261,7 @@ ttyclose(struct tty *tp)
|
||||
funsetown(&tp->t_sigio);
|
||||
s = spltty();
|
||||
if (constty == tp)
|
||||
constty = NULL;
|
||||
constty_clear();
|
||||
|
||||
ttyflush(tp, FREAD | FWRITE);
|
||||
clist_free_cblocks(&tp->t_canq);
|
||||
@ -871,9 +871,9 @@ ttioctl(struct tty *tp, u_long cmd, void *data, int flag)
|
||||
if (error)
|
||||
return (error);
|
||||
|
||||
constty = tp;
|
||||
constty_set(tp);
|
||||
} else if (tp == constty)
|
||||
constty = NULL;
|
||||
constty_clear();
|
||||
break;
|
||||
case TIOCDRAIN: /* wait till output drained */
|
||||
error = ttywait(tp);
|
||||
|
@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <sys/fcntl.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/msgbuf.h>
|
||||
#include <sys/namei.h>
|
||||
#include <sys/proc.h>
|
||||
#include <sys/queue.h>
|
||||
@ -117,11 +118,16 @@ int cons_unavail = 0; /* XXX:
|
||||
static int cn_mute;
|
||||
static int openflag; /* how /dev/console was opened */
|
||||
static int cn_is_open;
|
||||
static char *consbuf; /* buffer used by `consmsgbuf' */
|
||||
static struct callout conscallout; /* callout for outputting to constty */
|
||||
struct msgbuf consmsgbuf; /* message buffer for console tty */
|
||||
static u_char console_pausing; /* pause after each line during probe */
|
||||
static char *console_pausestr=
|
||||
"<pause; press any key to proceed to next line or '.' to end pause mode>";
|
||||
struct tty *constty; /* pointer to console "window" tty */
|
||||
|
||||
void cndebug(char *);
|
||||
static void constty_timeout(void *arg);
|
||||
|
||||
CONS_DRIVER(cons, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
SET_DECLARE(cons_set, struct consdev);
|
||||
@ -589,6 +595,70 @@ cndbctl(int on)
|
||||
refcount++;
|
||||
}
|
||||
|
||||
static int consmsgbuf_size = 8192;
|
||||
SYSCTL_INT(_kern, OID_AUTO, consmsgbuf_size, CTLFLAG_RW, &consmsgbuf_size, 0,
|
||||
"");
|
||||
|
||||
/*
|
||||
* Redirect console output to a tty.
|
||||
*/
|
||||
void
|
||||
constty_set(struct tty *tp)
|
||||
{
|
||||
int size;
|
||||
|
||||
KASSERT(tp != NULL, ("constty_set: NULL tp"));
|
||||
if (consbuf == NULL) {
|
||||
size = consmsgbuf_size;
|
||||
consbuf = malloc(size, M_TTYS, M_WAITOK);
|
||||
msgbuf_init(&consmsgbuf, consbuf, size);
|
||||
callout_init(&conscallout, 0);
|
||||
}
|
||||
constty = tp;
|
||||
constty_timeout(NULL);
|
||||
}
|
||||
|
||||
/*
|
||||
* Disable console redirection to a tty.
|
||||
*/
|
||||
void
|
||||
constty_clear(void)
|
||||
{
|
||||
int c;
|
||||
|
||||
constty = NULL;
|
||||
if (consbuf == NULL)
|
||||
return;
|
||||
callout_stop(&conscallout);
|
||||
while ((c = msgbuf_getchar(&consmsgbuf)) != -1)
|
||||
cnputc(c);
|
||||
free(consbuf, M_TTYS);
|
||||
consbuf = NULL;
|
||||
}
|
||||
|
||||
/* Times per second to check for pending console tty messages. */
|
||||
static int constty_wakeups_per_second = 5;
|
||||
SYSCTL_INT(_kern, OID_AUTO, constty_wakeups_per_second, CTLFLAG_RW,
|
||||
&constty_wakeups_per_second, 0, "");
|
||||
|
||||
static void
|
||||
constty_timeout(void *arg)
|
||||
{
|
||||
int c;
|
||||
|
||||
while (constty != NULL && (c = msgbuf_getchar(&consmsgbuf)) != -1) {
|
||||
if (tputchar(c, constty) < 0)
|
||||
constty = NULL;
|
||||
}
|
||||
if (constty != NULL) {
|
||||
callout_reset(&conscallout, hz / constty_wakeups_per_second,
|
||||
constty_timeout, NULL);
|
||||
} else {
|
||||
/* Deallocate the constty buffer memory. */
|
||||
constty_clear();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
cn_drvinit(void *unused)
|
||||
{
|
||||
|
@ -265,6 +265,7 @@ struct speedtab {
|
||||
#ifdef MALLOC_DECLARE
|
||||
MALLOC_DECLARE(M_TTYS);
|
||||
#endif
|
||||
extern struct msgbuf consmsgbuf; /* Message buffer for constty. */
|
||||
extern struct tty *constty; /* Temporary virtual console. */
|
||||
extern long tk_cancc;
|
||||
extern long tk_nin;
|
||||
@ -275,6 +276,8 @@ int b_to_q(char *cp, int cc, struct clist *q);
|
||||
void catq(struct clist *from, struct clist *to);
|
||||
void clist_alloc_cblocks(struct clist *q, int ccmax, int ccres);
|
||||
void clist_free_cblocks(struct clist *q);
|
||||
void constty_set(struct tty *tp);
|
||||
void constty_clear(void);
|
||||
int getc(struct clist *q);
|
||||
void ndflush(struct clist *q, int cc);
|
||||
char *nextc(struct clist *q, char *cp, int *c);
|
||||
|
Loading…
Reference in New Issue
Block a user