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);
/*