From dfa839c4e07d0e786f1c1d6701c5bde7df63bbe5 Mon Sep 17 00:00:00 2001 From: Andrey Prygunkov Date: Sun, 23 Mar 2008 15:26:07 +0000 Subject: [PATCH] added the automatic termination (killing) of post-process-script on server's shutdown --- PostInfo.cpp | 1 + PostInfo.h | 4 ++++ PrePostProcessor.cpp | 25 ++++++++++++++++++--- ScriptController.cpp | 53 ++++++++++++++++++++++++++++++++++++-------- ScriptController.h | 6 +++++ 5 files changed, 77 insertions(+), 12 deletions(-) diff --git a/PostInfo.cpp b/PostInfo.cpp index e8ce5954..3c6d3d8e 100644 --- a/PostInfo.cpp +++ b/PostInfo.cpp @@ -60,6 +60,7 @@ PostInfo::PostInfo() m_tStartTime = 0; m_tStageTime = 0; m_eStage = ptQueued; + m_pScriptThread = NULL; m_Messages.clear(); m_iIDGen++; m_iID = m_iIDGen; diff --git a/PostInfo.h b/PostInfo.h index dd3280c1..e260a948 100644 --- a/PostInfo.h +++ b/PostInfo.h @@ -29,6 +29,7 @@ #include #include "Log.h" +#include "Thread.h" class PostInfo { @@ -62,6 +63,7 @@ private: int m_iStageProgress; time_t m_tStartTime; time_t m_tStageTime; + Thread* m_pScriptThread; Mutex m_mutexLog; Messages m_Messages; @@ -100,6 +102,8 @@ public: bool GetParFailed() { return m_bParFailed; } void SetParFailed(bool bParFailed) { m_bParFailed = bParFailed; } void AppendMessage(Message::EKind eKind, const char* szText); + Thread* GetScriptThread() { return m_pScriptThread; } + void SetScriptThread(Thread* pScriptThread) { m_pScriptThread = pScriptThread; } Messages* LockMessages(); void UnlockMessages(); }; diff --git a/PrePostProcessor.cpp b/PrePostProcessor.cpp index 28a52387..d46338a2 100644 --- a/PrePostProcessor.cpp +++ b/PrePostProcessor.cpp @@ -171,8 +171,9 @@ void PrePostProcessor::Run() void PrePostProcessor::Stop() { Thread::Stop(); -#ifndef DISABLE_PARCHECK m_mutexQueue.Lock(); + +#ifndef DISABLE_PARCHECK if (m_ParChecker.IsRunning()) { m_ParChecker.Stop(); @@ -188,9 +189,21 @@ void PrePostProcessor::Stop() m_ParChecker.Kill(); } } - - m_mutexQueue.Unlock(); #endif + + if (!m_PostQueue.empty()) + { + PostInfo* pPostInfo = m_PostQueue.front(); + if (pPostInfo->GetStage() == PostInfo::ptExecutingScript && pPostInfo->GetScriptThread()) + { + Thread* pScriptThread = pPostInfo->GetScriptThread(); + pPostInfo->SetScriptThread(NULL); + pScriptThread->SetAutoDestroy(true); + pScriptThread->Stop(); + } + } + + m_mutexQueue.Unlock(); } void PrePostProcessor::QueueCoordinatorUpdate(Subject * Caller, void * Aspect) @@ -421,6 +434,12 @@ void PrePostProcessor::JobCompleted(PostInfo* pPostInfo) pPostInfo->SetProgressLabel(""); pPostInfo->SetStage(PostInfo::ptFinished); + if (pPostInfo->GetScriptThread()) + { + delete pPostInfo->GetScriptThread(); + pPostInfo->SetScriptThread(NULL); + } + #ifndef DISABLE_PARCHECK if (g_pOptions->GetParCleanupQueue() && IsNZBFileCompleted(NULL, pPostInfo->GetNZBFilename(), true, true, true) && diff --git a/ScriptController.cpp b/ScriptController.cpp index 70777b44..2242372f 100644 --- a/ScriptController.cpp +++ b/ScriptController.cpp @@ -75,12 +75,14 @@ void ScriptController::StartScriptJob(PostInfo* pPostInfo, const char* szScript, pScriptController->m_szScript = szScript; pScriptController->m_bNZBFileCompleted = bNZBFileCompleted; pScriptController->m_bHasFailedParJobs = bHasFailedParJobs; - pScriptController->SetAutoDestroy(true); + pScriptController->SetAutoDestroy(false); + + pPostInfo->SetScriptThread(pScriptController); pScriptController->Start(); // wait until process starts or fails to start - while (pPostInfo->GetWorking() && pPostInfo->GetStageProgress() == 0) + while (pPostInfo->GetWorking() && !pScriptController->m_hProcess) { usleep(50 * 1000); } @@ -147,7 +149,9 @@ void ScriptController::Run() m_pPostInfo->SetWorking(false); return; } - + + m_hProcess = ProcessInfo.hProcess; + /* close unused "write" end */ CloseHandle(hWritePipe); @@ -217,19 +221,18 @@ void ScriptController::Run() } // continue the first instance + m_hProcess = pid; /* close unused "write" end */ close(pipeout); #endif - m_pPostInfo->SetStageProgress(500); - /* open the read end */ FILE* readpipe = fdopen(pipein, "r"); char* buf = (char*)malloc(10240); debug("Entering pipe-loop"); - while (!feof(readpipe)) + while (!feof(readpipe) && !IsStopped()) { if (fgets(buf, 10240, readpipe)) { @@ -241,13 +244,22 @@ void ScriptController::Run() free(buf); fclose(readpipe); + if (IsStopped()) + { + warn("Interrupted post-process-script for %s", m_pPostInfo->GetInfoName()); + } + #ifdef WIN32 - WaitForSingleObject(ProcessInfo.hProcess, INFINITE); + WaitForSingleObject(m_hProcess, INFINITE); #else - waitpid(pid, NULL, 0); + waitpid(m_hProcess, NULL, 0); #endif - info("Completed post-process-script for %s", m_pPostInfo->GetInfoName()); + if (!IsStopped()) + { + info("Completed post-process-script for %s", m_pPostInfo->GetInfoName()); + } + m_pPostInfo->SetStage(PostInfo::ptFinished); m_pPostInfo->SetWorking(false); } @@ -352,3 +364,26 @@ void ScriptController::AddMessage(char* szText) } } } + +void ScriptController::Stop() +{ + debug("Stopping post-process-script"); + Thread::Stop(); + +#ifdef WIN32 + BOOL bOK = TerminateProcess(m_hProcess, -1); +#else + bool bOK = kill(m_hProcess, 9) == 0; +#endif + + if (bOK) + { + debug("Terminated post-process-script"); + } + else + { + error("Could not terminate post-process-script"); + } + + debug("Post-process-script stopped"); +} diff --git a/ScriptController.h b/ScriptController.h index a6a84d42..3aed8cc5 100644 --- a/ScriptController.h +++ b/ScriptController.h @@ -36,11 +36,17 @@ private: const char* m_szScript; bool m_bNZBFileCompleted; bool m_bHasFailedParJobs; +#ifdef WIN32 + HANDLE m_hProcess; +#else + pid_t m_hProcess; +#endif void AddMessage(char* szText); public: virtual void Run(); + virtual void Stop(); static void StartScriptJob(PostInfo* pPostInfo, const char* szScript, bool bNZBFileCompleted, bool bHasFailedParJobs); };