[Devel] [PATCH rh7] tty: Fix task hang if one of peers is sitting in read

Cyrill Gorcunov gorcunov at virtuozzo.com
Thu Jan 28 07:30:58 PST 2016


The locking scheme has been reworked significantly on current
vanilla kernel, so here is a minimal patch which eliminate
task hanging waiting for tty lock.

We've noticed this issue during our vtty console testing:
when we're entering into console the container spawns
"login" which calls vhangup and close all fds immediately,
so the "vzctl console" code continue hanging inside loop

 | vzctl waiting for password:
 |
 | [root at pcs7 ~]# cat /proc/2482/stack
 | [<ffffffff814b1935>] n_tty_read+0x336/0x721
 | [<ffffffff814accb4>] tty_read+0x89/0xcb
 | [<ffffffff81183651>] vfs_read+0xaf/0xf3
 | [<ffffffff81183d5f>] SyS_read+0x50/0x79
 | [<ffffffff817991b2>] system_call_fastpath+0x16/0x1b
 | [<ffffffffffffffff>] 0xffffffffffffffff
 |
 | login calls for vhangup
 |
 | [root at pcs7 ~]# cat /proc/2314/stack
 | [<ffffffff814b51ae>] __ldsem_down_write_nested+0xf7/0x1c6
 | [<ffffffff814b54cd>] ldsem_down_write_nested+0x38/0x3f
 | [<ffffffff814b37a4>] tty_ldisc_hangup+0xd1/0x1b9
 | [<ffffffff814aca10>] __tty_hangup+0x2d3/0x3a3
 | [<ffffffff814acaf0>] tty_vhangup+0x10/0x12
 | [<ffffffff814acd15>] tty_vhangup_self+0x1f/0x2a
 | [<ffffffff81182cf4>] sys_vhangup+0x20/0x27
 | [<ffffffff817991b2>] system_call_fastpath+0x16/0x1b
 | [<ffffffffffffffff>] 0xffffffffffffffff

The primary commit in vanilla kernel which address this

 | commit fae76e9adfa450f4c2dd5773265eb3c811a9c484
 | Author: Peter Hurley <peter at hurleysoftware.com>
 | Date:   Wed Nov 5 12:13:07 2014 -0500
 |
 |     tty: Fix hung task on pty hangup

Ufortunately it's not suitable to cherry-picking
because of related changes done in tty layer. So
I made kind of minimal fix which treats the issue

 - drop tty_ldisc_lock_pair and tty_unlock/tty_lock
   calls from tty_ldisc_hangup: sole locking of
   @ldisc_sem should be safe
 - same with tty_ldisc_release: no need for
   tty_lock_pair, plain @ldisc_sem taken on
   both ends with tty_ldisc_lock_pair help
   should order locking.

The tests in the bug are passed and "console"
action works as expected but better continue
wathing over tty layer.

https://jira.sw.ru/browse/PSBM-43454

Signed-off-by: Cyrill Gorcunov <gorcunov at virtuozzo.com>
CC: Vladimir Davydov <vdavydov at virtuozzo.com>
CC: Konstantin Khorenko <khorenko at virtuozzo.com>
---
 drivers/tty/tty_ldisc.c |    9 ++-------
 1 file changed, 2 insertions(+), 7 deletions(-)

Index: linux-pcs7.git/drivers/tty/tty_ldisc.c
===================================================================
--- linux-pcs7.git.orig/drivers/tty/tty_ldisc.c
+++ linux-pcs7.git/drivers/tty/tty_ldisc.c
@@ -679,16 +679,13 @@ void tty_ldisc_hangup(struct tty_struct
 	wake_up_interruptible_poll(&tty->write_wait, POLLOUT);
 	wake_up_interruptible_poll(&tty->read_wait, POLLIN);
 
-	tty_unlock(tty);
-
 	/*
 	 * Shutdown the current line discipline, and reset it to
 	 * N_TTY if need be.
 	 *
 	 * Avoid racing set_ldisc or tty_ldisc_release
 	 */
-	tty_ldisc_lock_pair(tty, tty->link);
-	tty_lock(tty);
+	tty_ldisc_lock(tty, MAX_SCHEDULE_TIMEOUT);
 
 	if (tty->ldisc) {
 
@@ -710,7 +707,7 @@ void tty_ldisc_hangup(struct tty_struct
 			WARN_ON(tty_ldisc_open(tty, tty->ldisc));
 		}
 	}
-	tty_ldisc_enable_pair(tty, tty->link);
+	tty_ldisc_unlock(tty);
 	if (reset)
 		tty_reset_termios(tty);
 
@@ -780,13 +777,11 @@ void tty_ldisc_release(struct tty_struct
 	tty_ldisc_debug(tty, "closing ldisc: %p\n", tty->ldisc);
 
 	tty_ldisc_lock_pair(tty, o_tty);
-	tty_lock_pair(tty, o_tty);
 
 	tty_ldisc_kill(tty);
 	if (o_tty)
 		tty_ldisc_kill(o_tty);
 
-	tty_unlock_pair(tty, o_tty);
 	tty_ldisc_unlock_pair(tty, o_tty);
 
 	/* And the memory resources remaining (buffers, termios) will be


More information about the Devel mailing list