fix signal-unsafe call inside of a signal

This commit is contained in:
badaix 2019-10-27 18:22:35 +01:00
parent f045602915
commit 1690f5ccc1
3 changed files with 41 additions and 48 deletions

View file

@ -16,6 +16,7 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
***/ ***/
#include <chrono>
#include <iostream> #include <iostream>
#include <sys/resource.h> #include <sys/resource.h>
@ -39,7 +40,7 @@
using namespace std; using namespace std;
using namespace popl; using namespace popl;
volatile sig_atomic_t g_terminated = false; using namespace std::chrono_literals;
PcmDevice getPcmDevice(const std::string& soundcard) PcmDevice getPcmDevice(const std::string& soundcard)
{ {
@ -172,11 +173,6 @@ int main(int argc, char** argv)
AixLog::Log::instance().add_logsink<AixLog::SinkCout>(AixLog::Severity::info, AixLog::Type::all, "%Y-%m-%d %H-%M-%S [#severity]"); AixLog::Log::instance().add_logsink<AixLog::SinkCout>(AixLog::Severity::info, AixLog::Type::all, "%Y-%m-%d %H-%M-%S [#severity]");
} }
signal(SIGHUP, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
#ifdef HAS_DAEMON #ifdef HAS_DAEMON
std::unique_ptr<Daemon> daemon; std::unique_ptr<Daemon> daemon;
if (daemonOption->is_set()) if (daemonOption->is_set())
@ -218,13 +214,24 @@ int main(int argc, char** argv)
} }
#endif #endif
auto signal_handler = install_signal_handler({SIGHUP, SIGTERM, SIGINT});
bool active = true;
if (host.empty()) if (host.empty())
{ {
#if defined(HAS_AVAHI) || defined(HAS_BONJOUR) #if defined(HAS_AVAHI) || defined(HAS_BONJOUR)
BrowseZeroConf browser; BrowseZeroConf browser;
mDNSResult avahiResult; mDNSResult avahiResult;
while (!g_terminated) while (true)
{ {
auto status = signal_handler.wait_for(500ms);
if (status == future_status::ready)
{
active = false;
int sig = signal_handler.get();
SLOG(INFO) << "Received signal " << sig << ": " << strsignal(sig) << "\n";
break;
}
cerr << "valid: " << signal_handler.valid() << ", status: " << (int)status << "\n";
try try
{ {
if (browser.browse("_snapcast._tcp", avahiResult, 5000)) if (browser.browse("_snapcast._tcp", avahiResult, 5000))
@ -241,24 +248,25 @@ int main(int argc, char** argv)
{ {
SLOG(ERROR) << "Exception: " << e.what() << std::endl; SLOG(ERROR) << "Exception: " << e.what() << std::endl;
} }
chronos::sleep(500);
} }
#endif #endif
} }
// Setup metadata handling if (active)
std::shared_ptr<MetadataAdapter> meta;
meta.reset(new MetadataAdapter);
if (metaStderr)
meta.reset(new MetaStderrAdapter);
std::unique_ptr<Controller> controller(new Controller(hostIdValue->value(), instance, meta));
if (!g_terminated)
{ {
// Setup metadata handling
std::shared_ptr<MetadataAdapter> meta;
meta.reset(new MetadataAdapter);
if (metaStderr)
meta.reset(new MetaStderrAdapter);
std::unique_ptr<Controller> controller(new Controller(hostIdValue->value(), instance, meta));
LOG(INFO) << "Latency: " << latency << "\n"; LOG(INFO) << "Latency: " << latency << "\n";
controller->start(pcmDevice, host, port, latency); controller->start(pcmDevice, host, port, latency);
while (!g_terminated) signal_handler.wait();
chronos::sleep(100); int sig = signal_handler.get();
SLOG(INFO) << "Received signal " << sig << ": " << strsignal(sig) << "\n";
controller->stop(); controller->stop();
} }
} }

View file

@ -16,34 +16,27 @@
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
***/ ***/
#ifndef SIGNAL_HANDLER_H #ifndef SIGNAL_HANDLER_HPP
#define SIGNAL_HANDLER_H #define SIGNAL_HANDLER_HPP
#include <future>
#include <set>
#include <signal.h> #include <signal.h>
#include <syslog.h>
extern volatile sig_atomic_t g_terminated;
void signal_handler(int sig) static std::future<int> install_signal_handler(std::set<int> signals)
{ {
static std::promise<int> promise;
std::future<int> future = promise.get_future();
switch (sig) for (auto signal : signals)
{ {
case SIGHUP: ::signal(signal, [](int sig) {
syslog(LOG_WARNING, "Received SIGHUP signal."); std::cerr << "signal: " << sig << "\n";
break; promise.set_value(sig);
case SIGTERM: });
syslog(LOG_WARNING, "Received SIGTERM signal.");
g_terminated = true;
break;
case SIGINT:
syslog(LOG_WARNING, "Received SIGINT signal.");
g_terminated = true;
break;
default:
syslog(LOG_WARNING, "Unhandled signal ");
break;
} }
return future;
} }
#endif #endif

View file

@ -40,9 +40,6 @@
#include "config.h" #include "config.h"
volatile sig_atomic_t g_terminated = false;
std::condition_variable terminateSignaled;
using namespace std; using namespace std;
using namespace popl; using namespace popl;
@ -201,10 +198,6 @@ int main(int argc, char* argv[])
settings.stream.pcmStreams.push_back(streamValue->value(n)); settings.stream.pcmStreams.push_back(streamValue->value(n));
} }
signal(SIGHUP, signal_handler);
signal(SIGTERM, signal_handler);
signal(SIGINT, signal_handler);
#ifdef HAS_DAEMON #ifdef HAS_DAEMON
std::unique_ptr<Daemon> daemon; std::unique_ptr<Daemon> daemon;
if (daemonOption->is_set()) if (daemonOption->is_set())
@ -270,9 +263,8 @@ int main(int argc, char* argv[])
std::thread t([&] { io_context.run(); }); std::thread t([&] { io_context.run(); });
while (!g_terminated) auto sig = install_signal_handler({SIGHUP, SIGTERM, SIGINT}).get();
chronos::sleep(100); SLOG(INFO) << "Received signal " << sig << ": " << strsignal(sig) << "\n";
io_context.stop(); io_context.stop();
t.join(); t.join();