From: David Herrmann Date: Sun, 2 Dec 2012 11:02:06 +0000 (+0100) Subject: uterm: vt: handle HUP on controlling TTY X-Git-Tag: kmscon-7~178 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=84a006777b0e18c1ffa49f3296534a7938c01b09;p=platform%2Fupstream%2Fkmscon.git uterm: vt: handle HUP on controlling TTY If the controlling TTY (in our case the VT) signals us a HUP, we should consider it closed and forward that to the caller. This does normally not happen on real VTs, however, on fake-VTs this happens if the parent goes away. We forward the HUP to the controlling subsystem which then has to deal with it. But more importantly, we disable the fd so we don't hog the CPU by unconditionally flushing the queue. Signed-off-by: David Herrmann --- diff --git a/src/uterm.h b/src/uterm.h index 382b16a..0844a9c 100644 --- a/src/uterm.h +++ b/src/uterm.h @@ -323,6 +323,7 @@ struct uterm_vt_master; enum uterm_vt_action { UTERM_VT_ACTIVATE, UTERM_VT_DEACTIVATE, + UTERM_VT_HUP, }; enum uterm_vt_flags { diff --git a/src/uterm_vt.c b/src/uterm_vt.c index 4c7c013..88fc924 100644 --- a/src/uterm_vt.c +++ b/src/uterm_vt.c @@ -62,6 +62,7 @@ struct uterm_vt { void *data; bool active; + bool hup; /* this is for *real* linux kernel VTs */ int real_fd; @@ -250,9 +251,22 @@ static void real_sig_leave(struct uterm_vt *vt, struct signalfd_siginfo *info) static void real_vt_input(struct ev_fd *fd, int mask, void *data) { struct uterm_vt *vt = data; + struct uterm_vt_event ev; /* we ignore input from the VT because we get it from evdev */ - tcflush(vt->real_fd, TCIFLUSH); + if (mask & EV_READABLE) + tcflush(vt->real_fd, TCIFLUSH); + + if (mask & (EV_HUP | EV_ERR)) { + log_debug("HUP on VT %d", vt->real_num); + ev_fd_disable(fd); + vt->hup = true; + if (vt->cb) { + memset(&ev, 0, sizeof(ev)); + ev.action = UTERM_VT_HUP; + vt->cb(vt, &ev, vt->data); + } + } } static int open_tty(const char *dev, int *tty_fd, int *tty_num) @@ -436,19 +450,19 @@ static void real_close(struct uterm_vt *vt) vt_call_deactivate(vt, true); ret = ioctl(vt->real_fd, KDSKBMODE, vt->real_kbmode); - if (ret) + if (ret && !vt->hup) log_error("cannot reset VT KBMODE to %d (%d): %m", vt->real_kbmode, errno); memset(&mode, 0, sizeof(mode)); mode.mode = VT_AUTO; ret = ioctl(vt->real_fd, VT_SETMODE, &mode); - if (ret) + if (ret && !vt->hup) log_warning("cannot reset VT %d to VT_AUTO mode (%d): %m", vt->real_num, errno); ret = ioctl(vt->real_fd, KDSETMODE, KD_TEXT); - if (ret) + if (ret && !vt->hup) log_warning("cannot reset VT %d to text-mode (%d): %m", vt->real_num, errno); @@ -472,6 +486,9 @@ static int real_activate(struct uterm_vt *vt) int ret; struct vt_stat vts; + if (vt->hup) + return -EPIPE; + ret = ioctl(vt->real_fd, VT_GETSTATE, &vts); if (ret) log_warn("cannot find current VT (%d): %m", errno); @@ -512,6 +529,9 @@ static int real_deactivate(struct uterm_vt *vt) int ret; struct vt_stat vts; + if (vt->hup) + return -EPIPE; + ret = ioctl(vt->real_fd, VT_GETSTATE, &vts); if (ret) { log_warn("cannot find current VT (%d): %m", errno); @@ -545,7 +565,7 @@ static void real_input(struct uterm_vt *vt, struct uterm_input_event *ev) struct vt_stat vts; int ret; - if (ev->handled || !vt->active) + if (ev->handled || !vt->active || vt->hup) return; ret = ioctl(vt->real_fd, VT_GETSTATE, &vts); @@ -593,6 +613,9 @@ static void real_retry(struct uterm_vt *vt) struct vt_stat vts; int ret; + if (vt->hup) + return; + ret = ioctl(vt->real_fd, VT_GETSTATE, &vts); if (ret) { log_warn("cannot find current VT (%d): %m", errno);