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

Reply via email to