tag 721421 patch
thanks

On Fri, Sep 26, 2014 at 11:12:06PM +0300, Niko Tyni wrote:

> The problem apparently happens when the timeout in the select loop
> (one second) triggers before execvp() has been called.
> 
> I can reproduce a similar "race" on my x86_64 machine by inserting a
> sleep(1) call right before the execvp() call.
> 
> I still haven't got to the bottom of it, but it looks like the gdb
> output is lost somewhere with select() timeouting (and returning zero)
> on subsequent calls too even though gdb has happily written to the pipe.

Further investigation with strace shows that the fd_set passed into
select() becomes empty if execvp() happens after the first select()
call. I was able to reproduce this with gdb replaced by a trivial program
that just prints to stdout (which greatly helped debugging.)

So I suppose the execvp() call somehow invalidates the fd set?

I haven't found an explanation for this observed behaviour. The closest
thing I was able to find was this in the select_tut(2) Linux manual page
(on Debian sid if that matters):

       11. Since  select()  modifies  its  file descriptor sets, if the
           call is being used in a loop, then the sets must be
           reinitialized before each call.

Reinitializing the set in the loop fixes it and seems to be the correct
thing to do anyway. Patch attached, this makes it work for me on both
mips and amd64.
-- 
Niko Tyni   nt...@debian.org
>From 88d953d71051fe45a4983f1cce9810f7ae942c56 Mon Sep 17 00:00:00 2001
From: Niko Tyni <nt...@debian.org>
Date: Sat, 27 Sep 2014 10:35:27 +0300
Subject: [PATCH] Reinitialize the fd set in the select loop

This fixes test failures on slow hosts.

It looks like execvp() happening in the child after the first select()
call invalidates the set.

Quoting the Linux select_tut(2) manual page:

 11. Since  select()  modifies  its  file descriptor sets, if the call
     is being used in a loop, then the sets must be reinitialized before
     each call.

Bug-Debian: https://bugs.debian.org/721421
---
 bt.xs | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/bt.xs b/bt.xs
index 6b9fed6..f892c8c 100644
--- a/bt.xs
+++ b/bt.xs
@@ -88,9 +88,6 @@ stack_trace (char **args)
         _exit(0);
     }
 
-    FD_ZERO(&fdset);
-    FD_SET(out_fd[0], &fdset);
-
     write(in_fd[1], "thread apply all backtrace\n", 27);
     write(in_fd[1], "quit\n", 5);
 
@@ -105,6 +102,9 @@ stack_trace (char **args)
         tv.tv_sec = 1;
         tv.tv_usec = 0;
 
+        FD_ZERO(&fdset);
+        FD_SET(out_fd[0], &fdset);
+
         sel = select(FD_SETSIZE, &fdset, NULL, NULL, &tv);
         if (sel == -1)
             break;
-- 
2.1.1

Reply via email to