mirror of https://github.com/kiwix/libkiwix.git
Add backend to launch subprocess.
The windows backend is not tested.
This commit is contained in:
parent
c351e7ccf1
commit
f3dd83907d
|
@ -6,6 +6,7 @@ kiwix_sources = [
|
|||
'reader.cpp',
|
||||
'entry.cpp',
|
||||
'searcher.cpp',
|
||||
'subprocess.cpp',
|
||||
'common/base64.cpp',
|
||||
'common/pathTools.cpp',
|
||||
'common/regexTools.cpp',
|
||||
|
@ -17,6 +18,12 @@ kiwix_sources = [
|
|||
]
|
||||
kiwix_sources += lib_resources
|
||||
|
||||
if host_machine.system() == 'windows'
|
||||
kiwix_sources += 'subprocess_windows.cpp'
|
||||
else
|
||||
kiwix_sources += 'subprocess_unix.cpp'
|
||||
endif
|
||||
|
||||
if xapian_dep.found()
|
||||
kiwix_sources += ['xapianSearcher.cpp']
|
||||
endif
|
||||
|
|
|
@ -0,0 +1,40 @@
|
|||
|
||||
|
||||
#include "subprocess.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
# include "subprocess_windows.h"
|
||||
#else
|
||||
# include "subprocess_unix.h"
|
||||
#endif
|
||||
|
||||
Subprocess::Subprocess(std::unique_ptr<SubprocessImpl> impl, const commandLine_t& commandLine) :
|
||||
mp_impl(std::move(impl))
|
||||
{
|
||||
mp_impl->run(commandLine);
|
||||
}
|
||||
|
||||
Subprocess::~Subprocess()
|
||||
{
|
||||
mp_impl->kill();
|
||||
}
|
||||
|
||||
std::unique_ptr<Subprocess> Subprocess::run(const commandLine_t& commandLine)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
auto impl = std::unique_ptr<SubprocessImpl>(new WinImpl);
|
||||
#else
|
||||
auto impl = std::unique_ptr<UnixImpl>(new UnixImpl);
|
||||
#endif
|
||||
return std::unique_ptr<Subprocess>(new Subprocess(std::move(impl), commandLine));
|
||||
}
|
||||
|
||||
bool Subprocess::isRunning()
|
||||
{
|
||||
return mp_impl->isRunning();
|
||||
}
|
||||
|
||||
bool Subprocess::kill()
|
||||
{
|
||||
return mp_impl->kill();
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
|
||||
#ifndef KIWIX_SUBPROCESS_H_
|
||||
#define KIWIX_SUBPROCESS_H_
|
||||
|
||||
#include <string>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<const char *> commandLine_t;
|
||||
|
||||
class SubprocessImpl
|
||||
{
|
||||
public:
|
||||
virtual void run(const commandLine_t& commandLine) = 0;
|
||||
virtual bool kill() = 0;
|
||||
virtual bool isRunning() = 0;
|
||||
virtual ~SubprocessImpl() = default;
|
||||
};
|
||||
|
||||
class Subprocess
|
||||
{
|
||||
private:
|
||||
// Impl depends of the system (window, unix, ...)
|
||||
std::unique_ptr<SubprocessImpl> mp_impl;
|
||||
Subprocess(std::unique_ptr<SubprocessImpl> impl, const commandLine_t& commandLine);
|
||||
|
||||
public:
|
||||
static std::unique_ptr<Subprocess> run(const commandLine_t& commandLine);
|
||||
~Subprocess();
|
||||
|
||||
bool isRunning();
|
||||
bool kill();
|
||||
};
|
||||
|
||||
|
||||
#endif // KIWIX_SUBPROCESS_H_
|
|
@ -0,0 +1,72 @@
|
|||
|
||||
|
||||
#include "subprocess_unix.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <iostream>
|
||||
#include <signal.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
UnixImpl::UnixImpl():
|
||||
m_pid(0),
|
||||
m_running(false),
|
||||
m_mutex(PTHREAD_MUTEX_INITIALIZER),
|
||||
m_waitingThread()
|
||||
{
|
||||
}
|
||||
|
||||
UnixImpl::~UnixImpl()
|
||||
{
|
||||
kill();
|
||||
pthread_cancel(m_waitingThread);
|
||||
}
|
||||
|
||||
void* UnixImpl::waitForPID(void* _self)
|
||||
{
|
||||
UnixImpl* self = static_cast<UnixImpl*>(_self);
|
||||
waitpid(self->m_pid, NULL, WEXITED);
|
||||
|
||||
pthread_mutex_lock(&self->m_mutex);
|
||||
self->m_running = false;
|
||||
pthread_mutex_unlock(&self->m_mutex);
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
void UnixImpl::run(const commandLine_t& commandLine)
|
||||
{
|
||||
const char* binary = commandLine[0];
|
||||
std::cerr << "running " << binary << std::endl;
|
||||
int pid = fork();
|
||||
switch(pid) {
|
||||
case -1:
|
||||
std::cerr << "cannot fork" << std::endl;
|
||||
break;
|
||||
case 0:
|
||||
if (execvp(binary, const_cast<char* const*>(commandLine.data()))) {
|
||||
perror("Cannot launch\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
break;
|
||||
default:
|
||||
m_pid = pid;
|
||||
m_running = true;
|
||||
pthread_create(&m_waitingThread, NULL, waitForPID, this);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool UnixImpl::kill()
|
||||
{
|
||||
return (::kill(m_pid, SIGKILL) == 0);
|
||||
}
|
||||
|
||||
bool UnixImpl::isRunning()
|
||||
{
|
||||
pthread_mutex_lock(&m_mutex);
|
||||
bool ret = m_running;
|
||||
pthread_mutex_unlock(&m_mutex);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
#ifndef KIWIX_SUBPROCESS_UNIX_H_
|
||||
#define KIWIX_SUBPROCESS_UNIX_H_
|
||||
|
||||
#include "subprocess.h"
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
|
||||
class UnixImpl : public SubprocessImpl
|
||||
{
|
||||
private:
|
||||
int m_pid;
|
||||
bool m_running;
|
||||
pthread_mutex_t m_mutex;
|
||||
pthread_t m_waitingThread;
|
||||
|
||||
public:
|
||||
UnixImpl();
|
||||
virtual ~UnixImpl();
|
||||
|
||||
void run(const commandLine_t& commandLine);
|
||||
bool kill();
|
||||
bool isRunning();
|
||||
|
||||
static void* waitForPID(void* self);
|
||||
};
|
||||
|
||||
#endif //KIWIX_SUBPROCESS_UNIX_H_
|
|
@ -0,0 +1,94 @@
|
|||
|
||||
|
||||
#include "subprocess_windows.h"
|
||||
|
||||
#include <windows.h>
|
||||
#include <winbase.h>
|
||||
#include <iostream>
|
||||
#include <sstream>
|
||||
|
||||
WinImpl::WinImpl():
|
||||
m_pid(0),
|
||||
m_running(false),
|
||||
m_handle(INVALID_HANDLE_VALUE)
|
||||
{
|
||||
InitializeCriticalSection(&m_criticalSection);
|
||||
}
|
||||
|
||||
WinImpl::~WinImpl()
|
||||
{
|
||||
kill();
|
||||
CloseHandle(m_handle);
|
||||
DeleteCriticalSection(&m_criticalSection);
|
||||
}
|
||||
|
||||
DWORD WINAPI WinImpl::waitForPID(void* _self)
|
||||
{
|
||||
WinImpl* self = static_cast<WinImpl*>(_self);
|
||||
WaitForSingleObject(self->m_handle, INFINITE);
|
||||
|
||||
EnterCriticalSection(&self->m_criticalSection);
|
||||
self->m_running = false;
|
||||
LeaveCriticalSection(&self->m_criticalSection);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
std::unique_ptr<wchar_t[]> toWideChar(const std::string& value)
|
||||
{
|
||||
auto size = MultiByteToWideChar(CP_UTF8, 0,
|
||||
value.c_str(), -1, nullptr, 0);
|
||||
auto wdata = std::unique_ptr<wchar_t[]>(new wchar_t[size]);
|
||||
auto ret = MultiByteToWideChar(CP_UTF8, 0,
|
||||
value.c_str(), -1, wdata.get(), size);
|
||||
if (0 == ret) {
|
||||
std::ostringstream oss;
|
||||
oss << "Cannot convert to wchar : " << GetLastError();
|
||||
throw std::runtime_error(oss.str());
|
||||
}
|
||||
return wdata;
|
||||
}
|
||||
|
||||
|
||||
void WinImpl::run(const commandLine_t& commandLine)
|
||||
{
|
||||
STARTUPINFOW startInfo = {0};
|
||||
PROCESS_INFORMATION procInfo;
|
||||
startInfo.cb = sizeof(startInfo);
|
||||
const char* binary = commandLine[0];
|
||||
std::cerr << "running " << binary << std::endl;
|
||||
std::ostringstream oss;
|
||||
for(auto& item: commandLine) {
|
||||
oss << item << " ";
|
||||
}
|
||||
if (CreateProcessW(
|
||||
toWideChar(binary).get(),
|
||||
toWideChar(oss.str()).get(),
|
||||
NULL,
|
||||
NULL,
|
||||
false,
|
||||
CREATE_NO_WINDOW,
|
||||
NULL,
|
||||
NULL,
|
||||
&startInfo,
|
||||
&procInfo)) {
|
||||
m_pid = procInfo.dwProcessId;
|
||||
m_handle = procInfo.hProcess;
|
||||
CloseHandle(procInfo.hThread);
|
||||
m_running = true;
|
||||
CreateThread(NULL, 0, &waitForPID, this, 0, NULL );
|
||||
}
|
||||
}
|
||||
|
||||
bool WinImpl::kill()
|
||||
{
|
||||
return TerminateProcess(m_handle, 0);
|
||||
}
|
||||
|
||||
bool WinImpl::isRunning()
|
||||
{
|
||||
EnterCriticalSection(&m_criticalSection);
|
||||
bool ret = m_running;
|
||||
LeaveCriticalSection(&m_criticalSection);
|
||||
return ret;
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
#ifndef KIWIX_SUBPROCESS_WINDOWS_H_
|
||||
#define KIWIX_SUBPROCESS_WINDOWS_H_
|
||||
|
||||
#include "subprocess.h"
|
||||
|
||||
#include <synchapi.h>
|
||||
|
||||
class WinImpl : public SubprocessImpl
|
||||
{
|
||||
private:
|
||||
int m_pid;
|
||||
bool m_running;
|
||||
HANDLE m_handle;
|
||||
CRITICAL_SECTION m_criticalSection;
|
||||
|
||||
public:
|
||||
WinImpl();
|
||||
virtual ~WinImpl();
|
||||
|
||||
void run(const commandLine_t& commandLine);
|
||||
bool kill();
|
||||
bool isRunning();
|
||||
|
||||
static DWORD WINAPI waitForPID(void* self);
|
||||
};
|
||||
|
||||
#endif //KIWIX_SUBPROCESS_WINDOWS_H_
|
Loading…
Reference in New Issue