0> In article <20121014231616.gn5...@codelibre.net>,
0> Roger Leigh <URL:mailto:rle...@codelibre.net> ("Roger") wrote:

Roger> This is quite an interesting problem, and will need a bit more
Roger> investigation before I find a solution.

I fully expected that!  :-)

I have however just tried a bit of experimentation, which does basically
what you suggest here:

Roger> I'll try trapping SIGCONT/SIGSTOP, and then raise the same signal
Roger> on ourselves.  However, this could open a horrible can of worms,
Roger> e.g. if you send SIGCONT to bash while schroot is stopped.

I've tried that scenario, and the child bash does continue okay when
given SIGCONT, and resuming schroot gets me back correctly.  Weird
things happen if the child exits when schroot is not in the foreground,
though - it seems that the parent (of schroot) is told to stop.  In
other words, if we do something like:

/--------
| ~$ schroot -d / -c child -u root
| /# suspend; exit
| 
| [1]+  Stopped                 schroot/schroot -d / -c child -u root
| ~$ bg
| [1]+ schroot/schroot -d / -c child -u root &
\--------

I get

/--------
| ~$ exit
| exit
\--------

without asking for it.  Since all my other tests are successful and I
don't know what causes the above, I present my patch below, in the hope
that someone can identify what's needed.  Admittedly, typing "suspend;
exit" (or even "suspend; exec <command>") seems a fairly oddball case.

If I use 'fg' rather than 'bg', it works; also if I start schroot
backgrounded, with a command such as 'schroot -- sleep 3 &' or
'schroot -- bash -c "sleep 3" &'.

If I use 'schroot -- bash -i -c "sleep 3" &', I get some strange
behaviour.  It stops itself, and if I immediately type 'fg' I get the
unasked-for exit (which can be prevented if you get bash to give
"There are stopped jobs."  message, by having another background
process).  A second 'fg' gets in, and the sleep runs.  If I first
just press enter, the parent notices schroot stop, but I still need
to 'fg' twice to get in.

Here's the patch I've been trying:

diff -u -x '*~' schroot-1.6.4/sbuild/sbuild-session.cc schroot-new/sbuild/sbuild-session.cc
--- schroot-1.6.4/sbuild/sbuild-session.cc	2012-10-27 23:39:05.000000000 +0100
+++ schroot-new/sbuild/sbuild-session.cc	2012-12-10 18:54:56.421884095 +0000
@@ -1431,7 +1431,7 @@
 	  child_killed = true;
 	}
 
-      if (waitpid(pid, &status, 0) == -1)
+      if (waitpid(pid, &status, WUNTRACED) == -1)
 	{
 	  if (errno == EINTR && (sighup_called || sigterm_called || sigint_called))
 	    continue; // Kill child and wait again.
@@ -1450,6 +1450,16 @@
 	}
       // No need to handle the SIGINT case here; it is handled
       // correctly below
+      else if (WIFSTOPPED(status))
+        {
+          siginfo_t info;
+          int stopsig = WSTOPSIG(status); // one of SIGSTOP, SIGTSTP, SIGTTIN, SIGTTOU
+          raise(stopsig);
+          // time passes ... when we come back, attempt to wake the child
+          // (which may now be a zombie, but that's fine):
+          kill(pid, SIGCONT);
+          continue;
+        }
       else
 	break;
     }

Reply via email to