diff --git a/src/index/indexer.cpp b/src/index/indexer.cpp index ab32f3dc..5ab0c8ee 100644 --- a/src/index/indexer.cpp +++ b/src/index/indexer.cpp @@ -32,6 +32,7 @@ static char rcsid[] = "@(#$Id: indexer.cpp,v 1.71 2008-12-17 08:01:40 dockes Exp #include "indexer.h" #include "fsindexer.h" #include "beaglequeue.h" +#include "mimehandler.h" #ifdef RCL_USE_ASPELL #include "rclaspell.h" @@ -97,7 +98,7 @@ bool ConfIndexer::index(bool resetbefore, ixType typestorun) createStemmingDatabases(); createAspellDict(); - + clearMimeHandlerCache(); return true; } diff --git a/src/internfile/mimehandler.cpp b/src/internfile/mimehandler.cpp index 9b8ae4ee..4f92624b 100644 --- a/src/internfile/mimehandler.cpp +++ b/src/internfile/mimehandler.cpp @@ -141,6 +141,17 @@ void returnMimeHandler(Dijon::Filter *handler) } } +void clearMimeHandlerCache() +{ + typedef multimap::value_type value_type; + map::iterator it; + for (it = o_handlers.begin(); it != o_handlers.end(); it++) { + delete it->second; + } + o_handlers.clear(); +} + + /* Get handler/filter object for given mime type: */ Dijon::Filter *getMimeHandler(const string &mtype, RclConfig *cfg, bool filtertypes) diff --git a/src/internfile/mimehandler.h b/src/internfile/mimehandler.h index 7866872b..b8e9a167 100644 --- a/src/internfile/mimehandler.h +++ b/src/internfile/mimehandler.h @@ -114,6 +114,11 @@ extern Dijon::Filter *getMimeHandler(const std::string &mtyp, RclConfig *cfg, /// Free up filter for reuse (you can also delete it) extern void returnMimeHandler(Dijon::Filter *); +/// Clean up cache at the end of an indexing pass. For people who use +/// the GUI to index: avoid all those filter processes forever hanging +/// off recoll. +extern void clearMimeHandlerCache(); + /// Can this mime type be interned ? extern bool canIntern(const std::string mimetype, RclConfig *cfg); diff --git a/src/utils/execmd.cpp b/src/utils/execmd.cpp index 4821bef8..a36be31a 100644 --- a/src/utils/execmd.cpp +++ b/src/utils/execmd.cpp @@ -128,27 +128,8 @@ public: if (!m_active || !m_parent) return; LOGDEB1(("~ExecCmdRsrc: working. mypid: %d\n", (int)getpid())); - int status; - if (m_parent->m_pid > 0) { - LOGDEB(("ExecCmd: killing cmd\n")); - pid_t grp = getpgid(m_parent->m_pid); - int ret = killpg(grp, SIGTERM); - if (ret == 0) { - for (int i = 0; i < 3; i++) { - (void)waitpid(m_parent->m_pid, &status, WNOHANG); - if (kill(m_parent->m_pid, 0) != 0) - break; - sleep(1); - if (i == 2) { - LOGDEB(("ExecCmd: killing (KILL) cmd\n")); - killpg(grp, SIGKILL); - } - } - } else { - LOGERR(("ExecCmd: error killing process group %d: %d\n", - grp, errno)); - } - } + + // Better to close the descs first in case the child is waiting in read if (m_parent->m_pipein[0] >= 0) close(m_parent->m_pipein[0]); if (m_parent->m_pipein[1] >= 0) @@ -157,6 +138,28 @@ public: close(m_parent->m_pipeout[0]); if (m_parent->m_pipeout[1] >= 0) close(m_parent->m_pipeout[1]); + int status; + if (m_parent->m_pid > 0) { + pid_t grp = getpgid(m_parent->m_pid); + LOGDEB2(("ExecCmd: killpg(%d, SIGTERM)\n", grp)); + int ret = killpg(grp, SIGTERM); + if (ret == 0) { + for (int i = 0; i < 3; i++) { + (void)waitpid(m_parent->m_pid, &status, WNOHANG); + if (kill(m_parent->m_pid, 0) != 0) + break; + sleep(1); + if (i == 2) { + LOGDEB(("ExecCmd: killpg(%d, SIGKILL)\n", grp)); + killpg(grp, SIGKILL); + (void)waitpid(m_parent->m_pid, &status, WNOHANG); + } + } + } else { + LOGERR(("ExecCmd: error killing process group %d: %d\n", + grp, errno)); + } + } m_parent->m_tocmd.release(); m_parent->m_fromcmd.release(); pthread_sigmask(SIG_UNBLOCK, &m_parent->m_blkcld, 0); @@ -474,8 +477,24 @@ void ExecCmd::dochild(const string &cmd, const list& args, bool has_input, bool has_output) { // Start our own process group - setpgid(0, getpid()); - + if (setpgid(0, getpid())) { + LOGINFO(("ExecCmd::dochild: setpgid(0, %d) failed: errno %d\n", + getpid(), errno)); + } + + // Restore SIGTERM to default. Really, signal handling should be + // specified when creating the execmd. Help Recoll get rid of its + // filter children though. To be fixed one day... Not sure that + // all of this is needed. But an ignored sigterm and the masks are + // normally inherited. + if (signal(SIGTERM, SIG_DFL) == SIG_ERR) { + LOGERR(("ExecCmd::dochild: signal() failed, errno %d\n", errno)); + } + sigset_t sset; + sigfillset(&sset); + pthread_sigmask(SIG_UNBLOCK, &sset, 0); + sigprocmask(SIG_UNBLOCK, &sset, 0); + if (has_input) { close(m_pipein[1]); m_pipein[1] = -1;