kcrash, fork, and stdout/stderr

David Faure faure at kde.org
Sun Dec 3 20:12:53 UTC 2017


On dimanche 3 décembre 2017 17:17:10 CET Michael Pyne wrote:
> On Sun, Dec 03, 2017 at 11:54:21AM +0100, David Faure wrote:
> > I'm trying to fix a bug (caught by CI) where KCrash, with the AutoRestart
> > flag, restarts the crashing process directly (fork+execve) rather than
> > via kdeinit.
> > 
> > The first process then exits, and whenever the child writes to stderr, it
> > gets a SIGPIPE. Oops.
> > 
> > How do I set things up so that the child's stderr is basically what the
> > parent's stderr was, in a way that works even if the parent exits?
> > 
> > I'm guessing something with dup() or dup2(), possibly?
> 
> This should already work, unless the O_CLOEXEC flag has been set on the
> file descriptor for stderr.  The kernel should duplicate open
> descriptors on fork(2), and exec(2) should maintain its association to
> any already-open descriptors.

Hmm then I don't understand the SIGPIPE.

> But, which process was the one writing to the terminal?  Do we know that
> the destination of stderr was a PTY instead of being filtered through
> some kind of kdeinit magic?

Yes, no kdeinit involved. Here's the setup:

$ bin/kcrashtest testAutoRestartDirectly
      starts test_crasher (with QProcess, using waitForFinished())
          which crashes :)
          KCrash catches that, and since the Autorestart flag is set, 
             sets the env var KCRASH_AUTO_RESTARTED,
             and starts test_crasher again (it checks that env var, so no infinite loop)

The first test_crasher then exits (after waitpid(), but that's just waiting for the child to start, right?).

That second test_crasher has debug output which leads to the SIGPIPE
write(2, "11:16:24.313 test_crasher(22916)"..., 119) = -1 EPIPE (Broken pipe)

Is this because QProcess set up something for catching stderr, which no longer exists
when the process exits?

Oh.....
proc.setProcessChannelMode(QProcess::ForwardedChannels);
fixes it!

Thanks for the rubber-ducking! Explaining the problem made me find the solution :-)

(BTW both test_crashers also append one line to a logfile, which the unittest polls, that's how
it checks that everything went fine).

> All this makes me wonder if it wouldn't be possible (and preferable) to
> have kdeinit handle the restart if it was responsible for the initial
> launch.

There might not be a kdeinit running at all, when a random Qt app links to KCrash and there is no plasma workspace around. Like on the CI, too.
I want a modular solution :)

-- 
David Faure, faure at kde.org, http://www.davidfaure.fr
Working on KDE Frameworks 5





More information about the Kde-frameworks-devel mailing list