diff options
author | Jeff Dike <jdike@addtoit.com> | 2007-12-01 15:16:30 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-12-03 11:13:17 -0500 |
commit | ce3b642d42f36406112ab474c03d81c5941d9398 (patch) | |
tree | 76a3c469248217a1d2e1648f749ad93864fe2856 /arch | |
parent | 0a765329ed656ef08915c8be4aba9031ba467ee4 (diff) |
uml: work around host tcsetattr bug
Under the conditions that UML uses it, tcgetattr is guaranteed to return
-EINTR when the console is attached to /dev/ptmx, making generic_console_write
hang because it loops, calling tcgetattr until it succeeds. This is a host
bug - see http://marc.info/?l=linux-kernel&m=119618990807182&w=2 for the
details.
This patch works around it by blocking SIGIO while the terminal attributes are
being fiddled.
Signed-off-by: Jeff Dike <jdike@linux.intel.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/um/drivers/chan_user.c | 11 |
1 files changed, 10 insertions, 1 deletions
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c index b88e93b3a39f..025764089ac8 100644 --- a/arch/um/drivers/chan_user.c +++ b/arch/um/drivers/chan_user.c | |||
@@ -74,10 +74,16 @@ void generic_free(void *data) | |||
74 | 74 | ||
75 | int generic_console_write(int fd, const char *buf, int n) | 75 | int generic_console_write(int fd, const char *buf, int n) |
76 | { | 76 | { |
77 | sigset_t old, no_sigio; | ||
77 | struct termios save, new; | 78 | struct termios save, new; |
78 | int err; | 79 | int err; |
79 | 80 | ||
80 | if (isatty(fd)) { | 81 | if (isatty(fd)) { |
82 | sigemptyset(&no_sigio); | ||
83 | sigaddset(&no_sigio, SIGIO); | ||
84 | if (sigprocmask(SIG_BLOCK, &no_sigio, &old)) | ||
85 | goto error; | ||
86 | |||
81 | CATCH_EINTR(err = tcgetattr(fd, &save)); | 87 | CATCH_EINTR(err = tcgetattr(fd, &save)); |
82 | if (err) | 88 | if (err) |
83 | goto error; | 89 | goto error; |
@@ -97,8 +103,11 @@ int generic_console_write(int fd, const char *buf, int n) | |||
97 | * Restore raw mode, in any case; we *must* ignore any error apart | 103 | * Restore raw mode, in any case; we *must* ignore any error apart |
98 | * EINTR, except for debug. | 104 | * EINTR, except for debug. |
99 | */ | 105 | */ |
100 | if (isatty(fd)) | 106 | if (isatty(fd)) { |
101 | CATCH_EINTR(tcsetattr(fd, TCSAFLUSH, &save)); | 107 | CATCH_EINTR(tcsetattr(fd, TCSAFLUSH, &save)); |
108 | sigprocmask(SIG_SETMASK, &old, NULL); | ||
109 | } | ||
110 | |||
102 | return err; | 111 | return err; |
103 | error: | 112 | error: |
104 | return -errno; | 113 | return -errno; |