diff options
Diffstat (limited to 'arch/um/os-Linux/sigio.c')
-rw-r--r-- | arch/um/os-Linux/sigio.c | 33 |
1 files changed, 27 insertions, 6 deletions
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c index 00e9388e947a..0ecac563c7b3 100644 --- a/arch/um/os-Linux/sigio.c +++ b/arch/um/os-Linux/sigio.c | |||
@@ -43,13 +43,13 @@ struct pollfds { | |||
43 | /* Protected by sigio_lock(). Used by the sigio thread, but the UML thread | 43 | /* Protected by sigio_lock(). Used by the sigio thread, but the UML thread |
44 | * synchronizes with it. | 44 | * synchronizes with it. |
45 | */ | 45 | */ |
46 | struct pollfds current_poll = { | 46 | static struct pollfds current_poll = { |
47 | .poll = NULL, | 47 | .poll = NULL, |
48 | .size = 0, | 48 | .size = 0, |
49 | .used = 0 | 49 | .used = 0 |
50 | }; | 50 | }; |
51 | 51 | ||
52 | struct pollfds next_poll = { | 52 | static struct pollfds next_poll = { |
53 | .poll = NULL, | 53 | .poll = NULL, |
54 | .size = 0, | 54 | .size = 0, |
55 | .used = 0 | 55 | .used = 0 |
@@ -156,7 +156,7 @@ static void update_thread(void) | |||
156 | set_signals(flags); | 156 | set_signals(flags); |
157 | } | 157 | } |
158 | 158 | ||
159 | int add_sigio_fd(int fd, int read) | 159 | static int add_sigio_fd(int fd, int read) |
160 | { | 160 | { |
161 | int err = 0, i, n, events; | 161 | int err = 0, i, n, events; |
162 | 162 | ||
@@ -191,6 +191,13 @@ int ignore_sigio_fd(int fd) | |||
191 | struct pollfd *p; | 191 | struct pollfd *p; |
192 | int err = 0, i, n = 0; | 192 | int err = 0, i, n = 0; |
193 | 193 | ||
194 | /* This is called from exitcalls elsewhere in UML - if | ||
195 | * sigio_cleanup has already run, then update_thread will hang | ||
196 | * or fail because the thread is no longer running. | ||
197 | */ | ||
198 | if(write_sigio_pid == -1) | ||
199 | return -EIO; | ||
200 | |||
194 | sigio_lock(); | 201 | sigio_lock(); |
195 | for(i = 0; i < current_poll.used; i++){ | 202 | for(i = 0; i < current_poll.used; i++){ |
196 | if(current_poll.poll[i].fd == fd) break; | 203 | if(current_poll.poll[i].fd == fd) break; |
@@ -215,7 +222,7 @@ int ignore_sigio_fd(int fd) | |||
215 | update_thread(); | 222 | update_thread(); |
216 | out: | 223 | out: |
217 | sigio_unlock(); | 224 | sigio_unlock(); |
218 | return(err); | 225 | return err; |
219 | } | 226 | } |
220 | 227 | ||
221 | static struct pollfd *setup_initial_poll(int fd) | 228 | static struct pollfd *setup_initial_poll(int fd) |
@@ -233,7 +240,7 @@ static struct pollfd *setup_initial_poll(int fd) | |||
233 | return p; | 240 | return p; |
234 | } | 241 | } |
235 | 242 | ||
236 | void write_sigio_workaround(void) | 243 | static void write_sigio_workaround(void) |
237 | { | 244 | { |
238 | unsigned long stack; | 245 | unsigned long stack; |
239 | struct pollfd *p; | 246 | struct pollfd *p; |
@@ -314,10 +321,24 @@ out_close1: | |||
314 | close(l_write_sigio_fds[1]); | 321 | close(l_write_sigio_fds[1]); |
315 | } | 322 | } |
316 | 323 | ||
317 | void sigio_cleanup(void) | 324 | void maybe_sigio_broken(int fd, int read) |
325 | { | ||
326 | if(!isatty(fd)) | ||
327 | return; | ||
328 | |||
329 | if((read || pty_output_sigio) && (!read || pty_close_sigio)) | ||
330 | return; | ||
331 | |||
332 | write_sigio_workaround(); | ||
333 | add_sigio_fd(fd, read); | ||
334 | } | ||
335 | |||
336 | static void sigio_cleanup(void) | ||
318 | { | 337 | { |
319 | if(write_sigio_pid != -1){ | 338 | if(write_sigio_pid != -1){ |
320 | os_kill_process(write_sigio_pid, 1); | 339 | os_kill_process(write_sigio_pid, 1); |
321 | write_sigio_pid = -1; | 340 | write_sigio_pid = -1; |
322 | } | 341 | } |
323 | } | 342 | } |
343 | |||
344 | __uml_exitcall(sigio_cleanup); | ||