diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2012-02-24 09:06:26 +0100 |
---|---|---|
committer | Marc-André Lureau <marcandre.lureau@redhat.com> | 2012-02-24 09:06:26 +0100 |
commit | 2e6edd64c473d1c0cdb45eaea151c83d367e9a49 (patch) | |
tree | 1ca21368ccef149887a4a0392bf36bb44477f77f /SpiceXPI | |
parent | a4dc304f2c3f3eeb6c1d715458cad7211bbc8c07 (diff) |
Avoid a race leading to a plugin crash
When the child exits quickly (failed to start etc..), it doesn't get
tracked properly and when receiving sigchld, "fake_this" may be NULL
leading to a crash (fake_this = s_children[info->si_pid])
Diffstat (limited to 'SpiceXPI')
-rw-r--r-- | SpiceXPI/src/plugin/plugin.cpp | 34 |
1 files changed, 31 insertions, 3 deletions
diff --git a/SpiceXPI/src/plugin/plugin.cpp b/SpiceXPI/src/plugin/plugin.cpp index b82d074..c3d2d91 100644 --- a/SpiceXPI/src/plugin/plugin.cpp +++ b/SpiceXPI/src/plugin/plugin.cpp @@ -569,10 +569,27 @@ void nsPluginInstance::Connect() return; } + /* use a pipe for the children to wait until it gets tracked */ + int pipe_fds[2] = { -1, -1 }; + if (pipe(pipe_fds) < 0) { + perror("spice-xpi system error"); + return; + } + pid_t child = fork(); LOG_DEBUG("child pid: " << child); if (child == 0) { + close (pipe_fds[1]); + pipe_fds[1] = -1; + + char c; + if (read(pipe_fds[0], &c, 1) != 0) + LOG_ERROR("Invalid read on pipe"); + + close (pipe_fds[0]); + pipe_fds[0] = -1; + execl("/usr/libexec/spice-xpi-client", "/usr/libexec/spice-xpi-client", NULL); LOG_ERROR("ERROR failed to run spice-xpi-client"); @@ -584,6 +601,14 @@ void nsPluginInstance::Connect() } else { + close(pipe_fds[0]); + pipe_fds[0] = -1; + + s_children[child] = this; + + close(pipe_fds[1]); + pipe_fds[1] = -1; + m_external_controller.SetFilename(socket_file); if (m_external_controller.Connect(10) != 0) @@ -659,8 +684,6 @@ void nsPluginInstance::Connect() // set connected status m_connected_status = -1; - - s_children[child] = this; } } @@ -765,6 +788,11 @@ void nsPluginInstance::SigchldRoutine(int sig, siginfo_t *info, void *uap) if (!getenv("SPICE_XPI_DEBUG")) { nsPluginInstance *fake_this = s_children[info->si_pid]; + if (fake_this == NULL) { + LOG_ERROR("Invalid children signal"); + return; + } + fake_this->CallOnDisconnected(exit_code); fake_this->m_external_controller.Disconnect(); } @@ -777,7 +805,7 @@ void nsPluginInstance::SigchldRoutine(int sig, siginfo_t *info, void *uap) // ============================== // // here the plugin is asked by Mozilla to tell if it is scriptable -// we should return a valid interface id and a pointer to +// we should return a valid interface id and a pointer to // nsScriptablePeer interface which we should have implemented // and which should be defined in the corressponding *.xpt file // in the bin/components folder |