Try to avoid avconv zombies
This commit is contained in:
@@ -33,6 +33,7 @@
|
|||||||
|
|
||||||
[UI]
|
[UI]
|
||||||
[Settings]
|
[Settings]
|
||||||
|
- increase the menu's width
|
||||||
- logout users that are being changed (loss of admin admin rights), or make sure they are still admin when they make changes
|
- logout users that are being changed (loss of admin admin rights), or make sure they are still admin when they make changes
|
||||||
- "signal not exposed" problem if a user logout and login again. bad resource destruction?
|
- "signal not exposed" problem if a user logout and login again. bad resource destruction?
|
||||||
[admin/DB]
|
[admin/DB]
|
||||||
|
|||||||
@@ -23,6 +23,11 @@ ServiceManager::ServiceManager()
|
|||||||
#endif // defined(SIGQUIT)
|
#endif // defined(SIGQUIT)
|
||||||
|
|
||||||
_signalSet.add(SIGHUP);
|
_signalSet.add(SIGHUP);
|
||||||
|
|
||||||
|
// Excplicitely ignore SIGCHLD to avoid zombies
|
||||||
|
// when avconv child processes are being killed
|
||||||
|
if (::signal(SIGCHLD, SIG_IGN) == SIG_ERR)
|
||||||
|
throw std::runtime_error("ServiceManager::ServiceManager, signal failed!");
|
||||||
}
|
}
|
||||||
|
|
||||||
ServiceManager::~ServiceManager()
|
ServiceManager::~ServiceManager()
|
||||||
|
|||||||
@@ -11,6 +11,8 @@
|
|||||||
namespace Transcode
|
namespace Transcode
|
||||||
{
|
{
|
||||||
|
|
||||||
|
boost::mutex AvConvTranscoder::_mutex;
|
||||||
|
|
||||||
boost::filesystem::path AvConvTranscoder::_avConvPath = "";
|
boost::filesystem::path AvConvTranscoder::_avConvPath = "";
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -109,15 +111,21 @@ AvConvTranscoder::AvConvTranscoder(const Parameters& parameters)
|
|||||||
|
|
||||||
std::cout << "executing... '" << oss.str() << "'" << std::endl;
|
std::cout << "executing... '" << oss.str() << "'" << std::endl;
|
||||||
|
|
||||||
std::vector<int> ranges = { 3, 1024 }; // fd range to be closed
|
// make sure only one thread is executing this part of code
|
||||||
_child = std::make_shared<boost::process::child>( boost::process::execute(
|
// See boost process FAQ
|
||||||
boost::process::initializers::run_exe(_avConvPath),
|
{
|
||||||
boost::process::initializers::set_cmd_line(oss.str()),
|
boost::lock_guard<boost::mutex> lock(_mutex);
|
||||||
boost::process::initializers::bind_stdout(sink),
|
std::vector<int> ranges = { 3, 1024 }; // fd range to be closed
|
||||||
boost::process::initializers::close_fd(STDIN_FILENO),
|
|
||||||
boost::process::initializers::close_fds(ranges)
|
_child = std::make_shared<boost::process::child>( boost::process::execute(
|
||||||
)
|
boost::process::initializers::run_exe(_avConvPath),
|
||||||
);
|
boost::process::initializers::set_cmd_line(oss.str()),
|
||||||
|
boost::process::initializers::bind_stdout(sink),
|
||||||
|
boost::process::initializers::close_fd(STDIN_FILENO),
|
||||||
|
boost::process::initializers::close_fds(ranges)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,34 +162,37 @@ AvConvTranscoder::~AvConvTranscoder()
|
|||||||
void
|
void
|
||||||
AvConvTranscoder::waitChild()
|
AvConvTranscoder::waitChild()
|
||||||
{
|
{
|
||||||
try {
|
if (_child)
|
||||||
if (_child) {
|
|
||||||
std::cout << "waiting for child!" << std::endl;
|
|
||||||
boost::process::wait_for_exit(*_child);
|
|
||||||
std::cout << "waiting for child! DONE" << std::endl;
|
|
||||||
_child.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( std::exception& e)
|
|
||||||
{
|
{
|
||||||
std::cerr << "Exception caugh in waitChild: " << e.what() << std::endl;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
|
std::cout << "waiting for child!" << std::endl;
|
||||||
|
boost::process::wait_for_exit(*_child, ec);
|
||||||
|
std::cout << "waiting for child! DONE." << std::endl;
|
||||||
|
|
||||||
|
if (ec)
|
||||||
|
std::cerr << "AvConvTranscoder::waitChild: error: " << ec.message() << std::endl;
|
||||||
|
|
||||||
|
_child.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AvConvTranscoder::killChild()
|
AvConvTranscoder::killChild()
|
||||||
{
|
{
|
||||||
try {
|
if (_child)
|
||||||
if (_child) {
|
|
||||||
std::cout << "Killing child!" << std::endl;
|
|
||||||
boost::process::terminate(*_child);
|
|
||||||
std::cout << "Killing child DONE" << std::endl;
|
|
||||||
_child.reset();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch( std::exception& e)
|
|
||||||
{
|
{
|
||||||
std::cerr << "Exception caugh in killChild: " << e.what() << std::endl;
|
boost::system::error_code ec;
|
||||||
|
|
||||||
|
std::cout << "Killing child! pid = " << _child->pid << std::endl;
|
||||||
|
boost::process::terminate(*_child, ec);
|
||||||
|
std::cout << "Killing child DONE" << std::endl;
|
||||||
|
|
||||||
|
// If an error occured, force kill the child
|
||||||
|
if (ec)
|
||||||
|
std::cerr << "AvConvTranscoder::killChild: error: " << ec.message() << std::endl;
|
||||||
|
|
||||||
|
_child.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,7 @@
|
|||||||
#include <boost/iostreams/stream.hpp>
|
#include <boost/iostreams/stream.hpp>
|
||||||
#include <boost/process.hpp>
|
#include <boost/process.hpp>
|
||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
#include "Parameters.hpp"
|
#include "Parameters.hpp"
|
||||||
|
|
||||||
@@ -43,6 +44,8 @@ class AvConvTranscoder
|
|||||||
|
|
||||||
const Parameters _parameters;
|
const Parameters _parameters;
|
||||||
|
|
||||||
|
static boost::mutex _mutex;
|
||||||
|
|
||||||
boost::process::pipe _outputPipe;
|
boost::process::pipe _outputPipe;
|
||||||
boost::iostreams::file_descriptor_source _source;
|
boost::iostreams::file_descriptor_source _source;
|
||||||
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> _is;
|
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> _is;
|
||||||
|
|||||||
Reference in New Issue
Block a user