Package: splashy Version: 0.3.8-1 Severity: normal Tags: patch When this simple test is run (on a single cpu system):
splashy boot sleep 5 splashy_update "getstring enter your name" splashy_update "exit" splashy appears to hang. The getstring prompt is not printed and splashy does not exit. If the F2 key is pressed a few times the getstring box suddenlt pops up and when the string is entered splasy exits. The problem is caused by a race between the socket loop and the keyevent loop. In the keyevent_loop we have: while (1) { ... pthread_mutex_lock (&key_mut); splashy_wait_for_event (); while ((key = splashy_get_key_event ()) > 0) { ... } pthread_mutex_unlock (&key_mut); ... } In the socket loop we try to synchronise with the keyevent loop using key_mut, for example to do a getpass we do: splashy_wake_up (); /* causes splashy_wait_for_event to exit */ pthread_mutex_lock (&key_mut); splashy_get_password (...); pthread_mutex_lock (&key_mut); Normaly keyevent_loop will be sleeping in splashy_wait_for_event, with the mutex locked. When a getpass command is read on the socket we call splashy_wake_up, which makes the keyevent_loop runnable. We then call pthread_mutex_lock, and so go to sleep. Now keyevent loop falls out of splashy_wait_for event, sees there are no keys to process, unlocks the mutex, LOOPS BACK AND RELOCKS THE MUTEX. The problem is that unlocking the mutex does not yield the cpu - the other thread stays asleep in pthread_mutex_lock. The fix is to inverse locking and waiting, in keyevent_loop do: while (1) { ... splashy_wait_for_event (); pthread_mutex_lock (&key_mut); ... pthread_mutex_unlock (&key_mut); } and in getpass: pthread_mutex_lock (&key_mut); splashy_wake_up (); splashy_get_password (...); pthread_mutex_unlock (&key_mut); Patch attached. -- System Information: Debian Release: lenny/sid APT prefers unstable APT policy: (500, 'unstable'), (500, 'testing'), (500, 'stable') Architecture: i386 (i686) Kernel: Linux 2.6.24-1-686 (SMP w/1 CPU core) Locale: LANG=en_US.UTF-8, LC_CTYPE=en_US.UTF-8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/bash Versions of packages splashy depends on: ii initramfs-tools 0.91e tools for generating an initramfs ii libc6 2.7-9 GNU C Library: Shared libraries ii libdirectfb-1.0-0 1.0.1-8 direct frame buffer graphics - sha ii libgcc1 1:4.3.0-2 GCC support library ii libglib2.0-0 2.16.1-2 The GLib library of C routines ii libmagic1 4.23-2 File type determination library us ii libsplashy1 0.3.8-1 Library to draw splash screen on b ii lsb-base 3.2-4 Linux Standard Base 3.2 init scrip ii zlib1g 1:1.2.3.3.dfsg-11 compression library - runtime splashy recommends no packages. -- no debconf information
diff --git a/src/splashy_functions.c b/src/splashy_functions.c index 16f630a..562d65f 100644 --- a/src/splashy_functions.c +++ b/src/splashy_functions.c @@ -375,26 +375,24 @@ cmd_repaint (void **args) gint cmd_getstring (void **args) { - /* Get the key event loop give up its lock */ - splashy_wake_up (); - + /* We want the keyboard */ pthread_mutex_lock(&key_mut); + /* Tell keyevent_loop to stop waiting for keyboard input */ + splashy_wake_up (); splashy_get_string((char *) args[1],*(int *) args[2], (char *) args[0]); pthread_mutex_unlock(&key_mut); - return 0; } gint cmd_getpass (void **args) { - /* Get the key event loop give up its lock */ + /* We want the keyboard */ + pthread_mutex_lock(&key_mut); + /* Tell keyevent_loop to stop waiting for keyboard input */ splashy_wake_up (); - - pthread_mutex_lock(&key_mut); splashy_get_password((char *) args[1],*(int *) args[2], (char *) args[0]); pthread_mutex_unlock(&key_mut); - return 0; } @@ -1047,8 +1045,10 @@ keyevent_loop (void *data) /* * sub-parent (we are a fork after all). init is our parent */ - pthread_mutex_lock(&key_mut); + /* Wait for keyboard input or getstring/getpass */ splashy_wait_for_event (); + /* seize the keyboard, blocking if getstring/getpass running */ + pthread_mutex_lock(&key_mut); /* * get all events from our event buffer (fifo queue) and * process them. @@ -1091,6 +1091,7 @@ keyevent_loop (void *data) } } } /* ends splashy_get_key_event */ + /* Let getstring or getpass run */ pthread_mutex_unlock(&key_mut); /*