[PATCH xorg-gtest 3/4] xserver: use new fork handling for signal masks
Peter Hutterer
peter.hutterer at who-t.net
Thu Oct 25 16:11:09 PDT 2012
The child must have SIGUSR1 set to SIG_IGN so the XServer will notify us
when it is ready to accept connection.
The parent must block SIGUSR1 until ready to receive them, but the server
must _not_ have that mask blocked. Otherwise, it won't react to VT switches.
Signed-off-by: Peter Hutterer <peter.hutterer at who-t.net>
---
src/xserver.cpp | 74 +++++++++++++++++++++++++++++++++++----------------------
1 file changed, 46 insertions(+), 28 deletions(-)
diff --git a/src/xserver.cpp b/src/xserver.cpp
index 9b163bb..9f91e7d 100644
--- a/src/xserver.cpp
+++ b/src/xserver.cpp
@@ -430,42 +430,60 @@ void xorg::testing::XServer::Start(const std::string &program) {
err_msg.append(std::strerror(errno));
throw std::runtime_error(err_msg);
}
- /* set SIGUSR1 handler to SIG_IGN, XServer tests for this and will
- * send SIGUSR1 when ready */
- if (SIG_ERR == signal(SIGUSR1, SIG_IGN)) {
- err_msg.append("Failed to set signal handler: ");
- err_msg.append(std::strerror(errno));
- throw std::runtime_error(err_msg);
- }
- args.push_back(std::string(GetDisplayString()));
+ pid_t pid = Fork();
+ if (pid == 0) {
+ /* set SIGUSR1 handler to SIG_IGN, XServer tests for this and will
+ * send SIGUSR1 when ready */
+ sighandler_t old_handler;
+ old_handler = signal(SIGUSR1, SIG_IGN);
+ if (old_handler == SIG_ERR) {
+ err_msg.append("Failed to set signal handler: ");
+ err_msg.append(std::strerror(errno));
+ throw std::runtime_error(err_msg);
+ }
- for (it = d_->options.begin(); it != d_->options.end(); it++) {
- args.push_back(it->first);
- if (!it->second.empty())
- args.push_back(it->second);
- }
+ /* unblock for the child process so the server receives SIGUSR1, needed
+ for VT switching */
+ sigemptyset(&sig_mask);
+ sigaddset(&sig_mask, SIGUSR1);
+ if (sigprocmask(SIG_UNBLOCK, &sig_mask, NULL)) {
+ err_msg.append("Failed to unblock signal mask: ");
+ err_msg.append(std::strerror(errno));
+ throw std::runtime_error(err_msg);
+ }
+
+ args.push_back(std::string(GetDisplayString()));
- Process::Start(program.empty() ? d_->path_to_server : program, args);
-
- if (Pid() > 0) {
- char *sleepwait = getenv("XORG_GTEST_XSERVER_SIGSTOP");
- if (sleepwait)
- raise(SIGSTOP);
-
- /* wait for SIGUSR1 from XServer */
- int recv_sig = sigtimedwait(&sig_mask, NULL, &sig_timeout);
- if (recv_sig == SIGCHLD) {
- GetState();
- } else if (recv_sig != SIGUSR1 && errno != EAGAIN) {
- err_msg.append("Error while waiting for XServer startup: ");
- err_msg.append(std::strerror(errno));
- throw std::runtime_error(err_msg);
+ for (it = d_->options.begin(); it != d_->options.end(); it++) {
+ args.push_back(it->first);
+ if (!it->second.empty())
+ args.push_back(it->second);
}
+
+ Process::Start(program.empty() ? d_->path_to_server : program, args);
+ /* noreturn */
+
+ }
+
+ /* parent */
+ char *sleepwait = getenv("XORG_GTEST_XSERVER_SIGSTOP");
+ if (sleepwait)
+ raise(SIGSTOP);
+
+ /* wait for SIGUSR1 from XServer */
+ int recv_sig = sigtimedwait(&sig_mask, NULL, &sig_timeout);
+ if (recv_sig == SIGCHLD) {
+ GetState();
+ } else if (recv_sig != SIGUSR1 && errno != EAGAIN) {
+ err_msg.append("Error while waiting for XServer startup: ");
+ err_msg.append(std::strerror(errno));
+ throw std::runtime_error(err_msg);
}
sigemptyset(&sig_mask);
sigaddset(&sig_mask, SIGCHLD);
+ sigaddset(&sig_mask, SIGUSR1);
sigprocmask(SIG_UNBLOCK, &sig_mask, NULL);
RegisterXIOErrorHandler();
--
1.7.11.7
More information about the xorg-devel
mailing list