aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorJeff Dike <jdike@addtoit.com>2006-03-27 04:14:40 -0500
committerLinus Torvalds <torvalds@g5.osdl.org>2006-03-27 11:44:38 -0500
commit5f4e8fd08f3993bc31a7dd91767fdb4da4fe6278 (patch)
tree8bd66ec07c3051d6f6e09fc53c7f2bde20c3c67d /arch
parent1fbbd6844e6a84e5d166ab475dc298d3b89fa4bf (diff)
[PATCH] uml: fix thread startup race
This fixes a race in the starting of write_sigio_thread. Previously, some of the data needed by the thread was initialized after the clone. If the thread ran immediately, it would see the uninitialized data, including an empty pollfds, which would cause it to hang. We move the data initialization to before the clone, and adjust the error paths and cleanup accordingly. Signed-off-by: Jeff Dike <jdike@addtoit.com> Cc: Paolo 'Blaisorblade' Giarrusso <blaisorblade@yahoo.it> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/um/os-Linux/sigio.c55
1 files changed, 27 insertions, 28 deletions
diff --git a/arch/um/os-Linux/sigio.c b/arch/um/os-Linux/sigio.c
index 7604c404c4c2..9ba942947146 100644
--- a/arch/um/os-Linux/sigio.c
+++ b/arch/um/os-Linux/sigio.c
@@ -29,8 +29,10 @@ static int write_sigio_pid = -1;
29 * the descriptors closed after it is killed. So, it can't see them change. 29 * the descriptors closed after it is killed. So, it can't see them change.
30 * On the UML side, they are changed under the sigio_lock. 30 * On the UML side, they are changed under the sigio_lock.
31 */ 31 */
32static int write_sigio_fds[2] = { -1, -1 }; 32#define SIGIO_FDS_INIT {-1, -1}
33static int sigio_private[2] = { -1, -1 }; 33
34static int write_sigio_fds[2] = SIGIO_FDS_INIT;
35static int sigio_private[2] = SIGIO_FDS_INIT;
34 36
35struct pollfds { 37struct pollfds {
36 struct pollfd *poll; 38 struct pollfd *poll;
@@ -270,49 +272,46 @@ void write_sigio_workaround(void)
270 /* Did we race? Don't try to optimize this, please, it's not so likely 272 /* Did we race? Don't try to optimize this, please, it's not so likely
271 * to happen, and no more than once at the boot. */ 273 * to happen, and no more than once at the boot. */
272 if(write_sigio_pid != -1) 274 if(write_sigio_pid != -1)
273 goto out_unlock; 275 goto out_free;
274
275 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
276 CLONE_FILES | CLONE_VM, &stack, 0);
277 276
278 if (write_sigio_pid < 0) 277 current_poll = ((struct pollfds) { .poll = p,
279 goto out_clear; 278 .used = 1,
279 .size = 1 });
280 280
281 if (write_sigio_irq(l_write_sigio_fds[0])) 281 if (write_sigio_irq(l_write_sigio_fds[0]))
282 goto out_kill; 282 goto out_clear_poll;
283 283
284 /* Success, finally. */
285 memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); 284 memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds));
286 memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); 285 memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private));
287 286
288 current_poll = ((struct pollfds) { .poll = p, 287 write_sigio_pid = run_helper_thread(write_sigio_thread, NULL,
289 .used = 1, 288 CLONE_FILES | CLONE_VM, &stack, 0);
290 .size = 1 });
291 289
292 sigio_unlock(); 290 if (write_sigio_pid < 0)
293 return; 291 goto out_clear;
294 292
295 out_kill:
296 l_write_sigio_pid = write_sigio_pid;
297 write_sigio_pid = -1;
298 sigio_unlock(); 293 sigio_unlock();
299 /* Going to call waitpid, avoid holding the lock. */ 294 return;
300 os_kill_process(l_write_sigio_pid, 1);
301 goto out_free;
302 295
303 out_clear: 296out_clear:
304 write_sigio_pid = -1; 297 write_sigio_pid = -1;
305 out_unlock: 298 write_sigio_fds[0] = -1;
306 sigio_unlock(); 299 write_sigio_fds[1] = -1;
307 out_free: 300 sigio_private[0] = -1;
301 sigio_private[1] = -1;
302out_clear_poll:
303 current_poll = ((struct pollfds) { .poll = NULL,
304 .size = 0,
305 .used = 0 });
306out_free:
308 kfree(p); 307 kfree(p);
309 out_close2: 308 sigio_unlock();
309out_close2:
310 close(l_sigio_private[0]); 310 close(l_sigio_private[0]);
311 close(l_sigio_private[1]); 311 close(l_sigio_private[1]);
312 out_close1: 312out_close1:
313 close(l_write_sigio_fds[0]); 313 close(l_write_sigio_fds[0]);
314 close(l_write_sigio_fds[1]); 314 close(l_write_sigio_fds[1]);
315 return;
316} 315}
317 316
318void sigio_cleanup(void) 317void sigio_cleanup(void)