[patch 3/3] uml: fix SIGWINCH handler race while waiting for signals.

From: blaisorblade
Date: Sat Jul 30 2005 - 14:10:26 EST

From: Bodo Stroesser <bstroesser@xxxxxxxxxxxxxxxxxxx>

If a SIGWINCH comes in, while winch_thread() isn't waiting
in wait(), winch_thread could miss signals.
It isn't very probable, that anyone will see this causing
trouble, as it would need a very special timing, that a
missed SIGWINCH results in a wrong window size.

So, this is a minor problem. But why not fix, as it can
be done so easy?

Signed-off-by: Bodo Stroesser <bstroesser@xxxxxxxxxxxxxxxxxxx>
Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade@xxxxxxxx>

linux-2.6.git-paolo/arch/um/drivers/chan_user.c | 11 ++++++-----
1 files changed, 6 insertions(+), 5 deletions(-)

diff -puN arch/um/drivers/chan_user.c~uml-fix-winch_thread arch/um/drivers/chan_user.c
--- linux-2.6.git/arch/um/drivers/chan_user.c~uml-fix-winch_thread 2005-07-30 18:03:31.000000000 +0200
+++ linux-2.6.git-paolo/arch/um/drivers/chan_user.c 2005-07-30 18:03:31.000000000 +0200
@@ -63,7 +63,7 @@ error:
* SIGWINCH can't be received synchronously, so you have to set up to receive it
* as a signal. That being the case, if you are going to wait for it, it is
- * convenient to sit in a pause() and wait for the signal to bounce you out of
+ * convenient to sit in sigsuspend() and wait for the signal to bounce you out of
* it (see below for how we make sure to exit only on SIGWINCH).

@@ -94,18 +94,19 @@ static int winch_thread(void *arg)
"byte, err = %d\n", -count);

/* We are not using SIG_IGN on purpose, so don't fix it as I thought to
- * do! If using SIG_IGN, the pause() call below would not stop on
+ * do! If using SIG_IGN, the sigsuspend() call below would not stop on

signal(SIGWINCH, winch_handler);
- sigdelset(&sigs, SIGWINCH);
- /* Block anything else than SIGWINCH. */
+ /* Block all signals possible. */
if(sigprocmask(SIG_SETMASK, &sigs, NULL) < 0){
printk("winch_thread : sigprocmask failed, errno = %d\n",
+ /* In sigsuspend(), block anything else than SIGWINCH. */
+ sigdelset(&sigs, SIGWINCH);

if(setsid() < 0){
printk("winch_thread : setsid failed, errno = %d\n", errno);
@@ -130,7 +131,7 @@ static int winch_thread(void *arg)
/* This will be interrupted by SIGWINCH only, since other signals
* are blocked.*/
- pause();
+ sigsuspend(&sigs);

count = os_write_file(pipe_fd, &c, sizeof(c));
if(count != sizeof(c))
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/