I am attempting to get a thread running which will be responsible for detecting a signal from any other thread within the same process.
sigset_t sigset;
sigfillset(&sigset);
pthread_sigmask( SIG_BLOCK, &sigset, &old );
Once i've done this, I then daemonize the process:
m_child = fork();
if (m_child == 0)
{
// Start the thread responsible for detecting a signal
}
This is done within another class called "SignalHandler" where the kick-off to this thread is done as follows:
m_pThread = new boost::thread( boost::bind(&SignalHandler::operator(), this ) );
and the functor operates in a tight loop as follows:
while (1)
{
if ( sigtimedwait( &sigset, &info, &ts ) == -1 )
{
if ( errno == EAGAIN || errno == EINTR )
{
std::cout << "Time-out waiting for signal" << std::endl;
}
throw SystemError( "sigtimedwait error" );
}
else
{
std::cout << "Detected a signal [" << info.si_signo << "]" << std::endl;
}
}
This works when I do a "kill -9 myProcess", but when I actually perform some illegal pointer manipulation (in any other thread), the process core dumps.
Why is the signal produced by the child thread not caught in my boost signal-catching thread?
Ah - I got it.
The problem is here:
sigset_t sigset;
sigfillset(&sigset);
pthread_sigmask( SIG_BLOCK, &sigset, &old );
Using sigfillset for pthread_sigmask is dangerous because blocking the synchronous signals causes undesirable effects.
If any of the SIGFPE, SIGILL, SIGSEGV,
or SIGBUS signals are generated while
they are blocked, the result is
undefined, unless the signal was
generated by the kill() function, the
sigqueue() function, or the raise()
function.
Related
I have a C++ program with a number of threads. At the start of the main thread (before any threads are spawned) I block SIGUSR1 using sigprocmask. I then create two threads, one waits for a SIGUSR1 using sigwait and the other monitors file descriptors using epoll_wait. For some reason when I send a SIGUSR1 to this program it is caught by the epoll_wait and not by the sigwait.
Linux Version 4.9.165
I have tried explicitly blocking the SIGUSR1 before calling epoll_wait but that does not solve the problem. I have also tried using epoll_pwait directly.
// main thread
// ...
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
pthread_sigmask(SIG_SETMASK, &sigset, NULL);
// ...
//thread 1
// ...
sigset_t sigset;
int sig;
sigemptyset(&sigset);
sigaddset(&sigset, SIGUSR1);
auto ret = sigwait(&sigset, &sig);
if (ret != 0)
{
std::cout << "sigwait failed\n";
}
// ...
//thread 2
static constexpr int MAX_EVENTS = 10;
struct epoll_event events[MAX_EVENTS];
int timeout = -1;
// ...
sigset_t oldset;
sigprocmask(SIG_SETMASK, NULL, &oldset);
std::cout << (sigismember(&oldset, SIGUSR1) ? "SIGUSR1 blocked " : "SIGUSR1 not blocked ") << "in epoll thread\n";
epoll_wait(epollFd.Get(), static_cast<struct epoll_event*>(events), MAX_EVENTS, timeout);
if (nfds < 0)
{
std::cout << "Epoll wait failed: " << strerror(errno) << '\n';
}
// ...
This gives me the output "Epoll wait failed: Interrupted system call" an the sigwait thread never wakes up.
I also see the "SIGUSR1 blocked in epoll thread" indicating that before the epoll_wait the SIGUSR1 signal was blocked.
My understanding is that child threads should inherit the signal masks of their parents, that the epoll_wait should be treated as an epoll_pwait with a null sigmask (and thus not alter the signal mask), and that the signal should go to the only thread that has the signal unblocked (being the one with sigwait). Am I incorrect?
I've been trying to switch my code from using one io_service per network connection to using shared ones, and I'm seeing some very odd behaviour on server sockets (client ones seem to work OK).
In order to try to work out what's going on I've re-started building up a simple example that will allow me to check my assumptions about everything that ought to happen. The first problem I've hit is that io_service::run doesn't exit when there are no handlers left, and as far as I can tell the handlers aren't removed from the work queue.
I have one thread that does an async_accept followed by an async_read. There is a separate client thread (which has its own io_service). The client thread's io_service is never run, and the server's one is run in yet another thread.
I'm using a condition variable to wait in the server thread for the read to complete (which will never happen as the client never writes). This times out just fine and then I call socket.cancel(). I would expect this to remove the read handler and run to exit as the work queue is now empty.
I do see the read handler get called (with a cancel error), but run never exits. When I tie the socket lifetime to the handler lifetime (by lambda capturing a shared_ptr to the socket) the memory isn't freed either.
The server is set up like this:
std::mutex mutex;
std::unique_lock<std::mutex> lock(mutex);
std::condition_variable signal;
boost::asio::io_service server_service;
boost::asio::ip::tcp::acceptor listener(server_service);
std::mutex read_mutex;
std::unique_lock<std::mutex> read_lock(read_mutex);
std::condition_variable read_done;
std::thread server([&]() {
std::unique_lock<std::mutex> lock(mutex);
listener.open(boost::asio::ip::tcp::v4());
listener.set_option(boost::asio::socket_base::enable_connection_aborted(true));
listener.bind(boost::asio::ip::tcp::endpoint(boost::asio::ip::tcp::v4(), 4567));
listener.listen();
std::shared_ptr<connection> server_cnx(new connection(server_service));
listener.async_accept(server_cnx->socket,
[&, server_cnx](const boost::system::error_code& error) {
log_thread() << "Server got a connection " << error << std::endl;
boost::asio::async_read_until(server_cnx->socket, server_cnx->buffer, '\n',
[&, server_cnx](const boost::system::error_code& error, std::size_t bytes) {
log_thread() << "Got " << bytes << ", " << error << std::endl;
std::unique_lock<std::mutex> lock(read_mutex);
lock.unlock();
read_done.notify_one();
});
});
lock.unlock();
signal.notify_one();
if ( read_done.wait_for(read_lock, std::chrono::seconds(1)) == std::cv_status::timeout ) {
log_thread() << "Server read timed out -- cancelling socket jobs" << std::endl;
server_cnx->socket.cancel();
server_cnx->socket.close();
} else {
log_thread() << "Server data read" << std::endl;
}
log_thread() << "Exiting server thread" << std::endl;
});
signal.wait(lock);
log_thread() << "Server set up" << std::endl;
The io_service thread is set up like this:
std::thread server_io([&]() {
log_thread() << "About to service server IO requests" << std::endl;
try {
server_service.run();
} catch ( ... ) {
log_thread() << "Exception caught" << std::endl;
}
log_thread() << "**** Service jobs all run" << std::endl;
signal.notify_one();
});
The output is as follows:
10.0002 139992957945728 Server set up
10.0005 139992957945728 Client set up
10.0006 139992848398080 About to service server IO requests
10.0006 139992848398080 Server got a connection system:0
11.0003 139992934819584 Server read timed out -- cancelling socket jobs
11.0004 139992934819584 Exiting server thread
11.0004 139992848398080 Got 0, system:125
20.0006 139992957945728 IO thread timed out servicing requests -- stopping it
^^^ This should not happen because the server service should have run out of work
20.0006 139992957945728 Waiting for things to close....
22.0008 139992957945728 Wait over, exiting
(Columns are time + 10s, thread ID, log message)
At the 11 second mark you can see that the async_read_until is called. This is the last handler in the server's io_service and yet run doesn't exit.
Even after the time out waiting for run to exit fires and the waiting thread does io_service::stop(), still run doesn't exit (there's another 2 second wait there).
The full code is on github
The program is invoking undefined behavior when the server thread attempts to unlock the read_lock that it does not own.
int main()
{
...
std::mutex read_mutex;
std::unique_lock<std::mutex> read_lock(read_mutex); // Acquired by main.
std::condition_variable read_done;
std::thread server([&]() { // Capture lock reference.
std::unique_lock<std::mutex> lock(mutex);
...
// The next line invokes undefined behavior as this thread does did
// not acquire read_lock.mutex().
if (read_done.wait_for(read_lock, ...)
// ^^^^^^^^^ caller does not own.
{
...
}
});
signal.wait(lock);
...
}
In particular, when invoking condition_variable::wait_for(lock), the standard requires that lock.owns_lock() is true and lock.mutex() is locked by the calling thread.
Mixing synchronous and asynchronous flows often add complexity. In this particular case, where the synchronous calls are intertwined throughout each layer using lower-level constructs for event/signal notification without a persisted state, I think that it adds unnecessary complexity and overcomplicates the flow. Furthermore, the broad scope of variables can add complexity. If read_lock had never been captured by the lambdas, then a compiler error would have occurred.
Consider the separation in space when trying to observe two events:
// I will eventually be interested when the server starts
// accepting connections, so start setting up now.
std::mutex server_mutex;
std::unique_lock<std::mutex> server_lock(server_mutex);
std::condition_variable server_started;
std::thread server([&]()
{
// I will eventually be interested when the server reads
// data, so start setting up now.
std::mutex read_mutex;
std::unique_lock<std::mutex> read_lock(read_mutex);
std::condition_variable read_done;
listener.async_accept(...,
[&](...)
{
// Got connection.
async_read_until(...,
[&](...)
{
// Someone may be interested that data has been read,
// so use the correct mutex and condition_variable
// pair.
std::unique_lock<std::mutex> read_lock(read_mutex);
read_lock.unlock();
read_done.notify_one();
});
}); // async_accept
// Someone may be interested that I am accepting connections,
// so use the correct mutex and condition_variable pair.
std::unique_lock<std::mutex> server_lock(server_mutex);
server_lock.unlock();
server_done.notify_one();
// I am now interested in if data has been read.
read_done.wait_for(read_lock);
}); // server thread
// I am now interested in if the server has started.
server_started.wait(server_lock);
The caller has to prepare to handle an event, start an operation, then wait for the event, and the operation must know the event the caller is interested in. To worsen the situation, one must now consider lock ordering to prevent deadlocks. Note how in the above example, the server thread acquires the read_mutex and then the server_mutex. Another thread cannot acquire the mutexes in a difference order without introducing the chance of a deadlock. In terms of complexity, this approach scales poorly with the number of events.
It may be worth considering re-examining the program's flow and control structure. If it can be written to be primarily asynchronous, then callback chains, continuations, or a signal-and-slot system (Boost.Signals) may uncomplicate the solution. If one prefers to have asynchronous code read as if it was synchronous, then Boost.Asio's support for coroutines can provide a clean solution. Finally, if one needs to synchronously wait on an asynchronous operation's result or timeout, then consider using Boost.Asio's support for std::future or using them directly.
// Use an asynchronous operation so that it can be cancelled on timeout.
std::future<std::size_t> on_read = boost::asio::async_read_until(
socket, buffer, '\n',boost::asio::use_future);
// If timeout occurs, then cancel the operation.
if (on_read.wait_for(std::chrono::seconds(1)) == std::future_status::timeout)
{
socket.cancel();
}
// Otherwise, the operation completed (with success or error).
else
{
// If the operation failed, then on_read.get() will throw a
// boost::system::system_error.
auto bytes_transferred = on_read.get();
}
While I would strongly advocate re-examining the overall control structure and reducing variable scope, the following sample is roughly equivalent to the above example, but may be slightly easier to maintain with its use of std::future:
// I will eventually be interested when the server starts
// accepting connections, so start setting up now.
std::promise<void> server_started_promise;
auto server_started = server_started_promise.get_future();
std::thread server([&]()
{
// I will eventually be interested when the server reads
// data, so start setting up now.
std::promise<void> read_done_promise;
auto read_done = read_done_promise.get_future();
listener.async_accept(...,
[&](...)
{
// Got connection.
async_read_until(...,
[&](...)
{
// Someone may be interested that data has been read.
read_done_promise.set_value();
});
}); // async_accept
// Someone may be interested that I am accepting connections.
server_started_promise.set_value();
// I am now interested in if data has been read.
read_done.wait_for(...);
}); // server thread
// I am now interested in if the server has started.
server_started.wait();
Here is a complete example based on the original code that demonstrates using std::future to control flow and timeout asynchronous operations in a synchronous manner:
#include <future>
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
#include <boost/asio/use_future.hpp>
#include <boost/optional.hpp>
#include <boost/utility/in_place_factory.hpp>
int main()
{
using boost::asio::ip::tcp;
// Setup server thread.
boost::asio::io_service server_io_service;
std::promise<tcp::endpoint> server_promise;
auto server_future = server_promise.get_future();
// Start server thread.
std::thread server_thread(
[&server_io_service, &server_promise]
{
tcp::acceptor acceptor(server_io_service);
acceptor.open(tcp::v4());
acceptor.set_option(
boost::asio::socket_base::enable_connection_aborted(true));
acceptor.bind(tcp::endpoint(tcp::v4(), 0));
acceptor.listen();
// Handlers will not chain work, so control the io_service with a work
// object.
boost::optional<boost::asio::io_service::work> work(
boost::in_place(std::ref(server_io_service)));
// Accept a connection.
tcp::socket server_socket(server_io_service);
auto on_accept = acceptor.async_accept(server_socket,
boost::asio::use_future);
// Server has started, so notify caller.
server_promise.set_value(acceptor.local_endpoint());
// Wait for connection or error.
boost::system::system_error error =
make_error_code(boost::system::errc::success);
try
{
on_accept.get();
}
catch (const boost::system::system_error& e)
{
error = e;
}
std::cout << "Server got a connection " << error.code() << std::endl;
// Read from connection.
boost::asio::streambuf buffer;
auto on_read = boost::asio::async_read_until(
server_socket, buffer, '\n', boost::asio::use_future);
// The async_read operation is work, so destroy the work object allowing
// run() to exit.
work = boost::none;
// Timeout the async read operation.
if (on_read.wait_for(std::chrono::seconds(1)) ==
std::future_status::timeout)
{
std::cout << "Server read timed out -- cancelling socket jobs"
<< std::endl;
server_socket.close();
}
else
{
error = make_error_code(boost::system::errc::success);
std::size_t bytes_transferred = 0;
try
{
bytes_transferred = on_read.get();
}
catch (const boost::system::system_error& e)
{
error = e;
}
std::cout << "Got " << bytes_transferred << ", "
<< error.code() << std::endl;
}
std::cout << "Exiting server thread" << std::endl;
});
// Wait for server to start accepting connections.
auto server_endpoint = server_future.get();
std::cout << "Server set up" << std::endl;
// Client thread.
std::promise<void> promise;
auto future = promise.get_future();
std::thread client_thread(
[&server_endpoint, &promise]
{
boost::asio::io_service io_service;
tcp::socket client_socket(io_service);
boost::system::error_code error;
client_socket.connect(server_endpoint, error);
std::cout << "Connected " << error << std::endl;
promise.set_value();
// Keep client socket alive, allowing server to timeout.
std::this_thread::sleep_for(std::chrono::seconds(2));
std::cout << "Exiting client thread" << std::endl;
});
// Wait for client to connect.
future.get();
std::cout << "Client set up" << std::endl;
// Reset generic promise and future.
promise = std::promise<void>();
future = promise.get_future();
// Run server's io_service.
std::thread server_io_thread(
[&server_io_service, &promise]
{
std::cout << "About to service server IO requests" << std::endl;
try
{
server_io_service.run();
}
catch (const std::exception& e)
{
std::cout << "Exception caught: " << e.what() << std::endl;
}
std::cout << "Service jobs all run" << std::endl;
promise.set_value();
});
if (future.wait_for(std::chrono::seconds(3)) ==
std::future_status::timeout)
{
std::cout << "IO thread timed out servicing requests -- stopping it"
<< std::endl;
server_io_service.stop();
}
// Join all threads.
server_io_thread.join();
server_thread.join();
client_thread.join();
}
So of course this multi-threading is a tricky business. Turns out that in this case the read lock is acquired in the wrong place so the handler is being blocked by the thread waiting for it to complete.
I guess the lesson here is to never handle thread locks without some sort of time out.
I am in the middle of developing a game and came across the problem of multithreading. I already used multithreading successfully when loading resources. I did that by creating some threads at some point, assigned them functions, and waited for them to finish, while drawing a loading screen, pretty straightforward.
Now I want to create some threads, that can wait idle till they receive a function, when they do, solve that, then stay idle again. They must operate in a game loop, which is roughly like this (I came up with these function names just for easy visualization):
std::thread t0,t1;
while(gamerunning)
{
UpdateGame();
t0.receiveFunc( RenderShadow );
t1.receiveFunc( RenderScene );
WaitForThreadstoFinishWork();
RenderEverything(); //Only draw everything if the threads finished (D3D11's Deferred Context rendering)
}
t0.Destroy();
t1.Destroy();
My rendering engine is working, and for the time being (for testing), I created threads in my game loop, which is a terrible way of even a quick test, because my rendering speed even slowed down. By the way, I am using C++11's library.
Long story short, I want to create threads before my game loop takes place, and use those in the game loop afterwards, hope someone can help me out. If it is an option, I would really want to stay away from the lower levels of threading, I just need the most straightforward way of doing this.
Following your most recent comments, here is an example implementation of a thread that wakes up on demand, runs its corresponding task and then goes back to sleep, along with the necessary functions to manage it (wait for task completion, ask for shutdown, wait for shutdown).
Since your set of functions is fixed, all you'll have left to do is to create as much threads as you need (ie. 7, probably in a vector), each with its own corresponding task.
Note that once you remove the debugging couts there's little code left, so I don't think there is a need to explain the code (it's pretty self-explanatory IMHO). However don't hesitate to ask if you need explanations on some details.
class TaskThread {
public:
TaskThread(std::function<void ()> task)
: m_task(std::move(task)),
m_wakeup(false),
m_stop(false),
m_thread(&TaskThread::taskFunc, this)
{}
~TaskThread() { stop(); join(); }
// wake up the thread and execute the task
void wakeup() {
auto lock = std::unique_lock<std::mutex>(m_wakemutex);
std::cout << "main: sending wakeup signal..." << std::endl;
m_wakeup = true;
m_wakecond.notify_one();
}
// wait for the task to complete
void wait() {
auto lock = std::unique_lock<std::mutex>(m_waitmutex);
std::cout << "main: waiting for task completion..." << std::endl;
while (m_wakeup)
m_waitcond.wait(lock);
std::cout << "main: task completed!" << std::endl;
}
// ask the thread to stop
void stop() {
auto lock = std::unique_lock<std::mutex>(m_wakemutex);
std::cout << "main: sending stop signal..." << std::endl;
m_stop = true;
m_wakecond.notify_one();
}
// wait for the thread to actually be stopped
void join() {
std::cout << "main: waiting for join..." << std::endl;
m_thread.join();
std::cout << "main: joined!" << std::endl;
}
private:
std::function<void ()> m_task;
// wake up the thread
std::atomic<bool> m_wakeup;
bool m_stop;
std::mutex m_wakemutex;
std::condition_variable m_wakecond;
// wait for the thread to finish its task
std::mutex m_waitmutex;
std::condition_variable m_waitcond;
std::thread m_thread;
void taskFunc() {
while (true) {
{
auto lock = std::unique_lock<std::mutex>(m_wakemutex);
std::cout << "thread: waiting for wakeup or stop signal..." << std::endl;
while (!m_wakeup && !m_stop)
m_wakecond.wait(lock);
if (m_stop) {
std::cout << "thread: got stop signal!" << std::endl;
return;
}
std::cout << "thread: got wakeup signal!" << std::endl;
}
std::cout << "thread: running the task..." << std::endl;
// you should probably do something cleaner than catch (...)
// just ensure that no exception propagates from m_task() to taskFunc()
try { m_task(); } catch (...) {}
std::cout << "thread: task completed!" << std::endl;
std::cout << "thread: sending task completed signal..." << std::endl;
// m_wakeup is atomic so there is no concurrency issue with wait()
m_wakeup = false;
m_waitcond.notify_all();
}
}
};
int main()
{
// example thread, you should really make a pool (eg. vector<TaskThread>)
TaskThread thread([]() { std::cout << "task: running!" << std::endl; });
for (int i = 0; i < 2; ++i) { // dummy example loop
thread.wakeup();
// wake up other threads in your thread pool
thread.wait();
// wait for other threads in your thread pool
}
}
Here's what I get (actual order varies from run to run depending on thread scheduling):
main: sending wakeup signal...
main: waiting for task completion...
thread: waiting for wakeup or stop signal...
thread: got wakeup signal!
thread: running the task...
task: running!
thread: task completed!
thread: sending task completed signal...
thread: waiting for wakeup or stop signal...
main: task completed!
main: sending wakeup signal...
main: waiting for task completion...
thread: got wakeup signal!
thread: running the task...
task: running!
thread: task completed!
thread: sending task completed signal...
thread: waiting for wakeup or stop signal...
main: task completed!
main: sending stop signal...
main: waiting for join...
thread: got stop signal!
main: joined!
After several days of searching it's time to ask. Environment is Ubuntu 12.04/Gnome.
I'm developing some embedded code on the ubuntu box and testing as much as I can in that environment before porting over to the embedded processor. The current routine is a real time fast fourier transform and I want to use gnuplot to display the results. So I want my test code AND gnuplot to run in the foreground at the same time and communicate via a pipe.
I did the usual popen() call and that worked except for one thing. stdin for the child (gnuplot) is still attached to the console. It is in contention with the parent process. The parent process needs to receive keystrokes to modify its behaviour. Sometimes the parent gets the keystroke and sometimes gnuplot does.
So I've tried the fork/exec path. Specifically
pid_t pg = tcgetpgrp(1); // get process group associated with stdout
cerr << "pid_t pg = " << pg << endl;
cerr << "process pid is " << getpid() << endl;
if (pipe(pipefd) == -1) {// open the pipe
cerr << "pipe failure" << endl;
exit(3);
} // if pipe
cpid = fork();
if (cpid == -1) {
cerr << "fork failure" << endl;
exit(1);
}
if (cpid == 0) { // this is the child process
if (tcsetpgrp(1, pg) == -1) { // this should set the process associated with stdin (gnuplot) with the
cerr << "tcsetgrp failed" << endl; // foreground terminal.
exit(7);
}
close(pipefd[1]); // close child's writing handle
if (pipefd[0] != STDIN_FILENO) { // this changes the file descripter of stdin back to 0
if ( dup2(pipefd[0], STDIN_FILENO) != STDIN_FILENO) {
cerr << "dup2 error on stdin" << endl;
exit(6);
}
}
if (execl("/usr/bin/gnuplot", "gnuplot", "-background", "white", "-raise", (char *) NULL)) {
cerr << "execl failed" << endl;
exit(2);
} else // if exec
close(pipefd[0]); // close parent's reading handle
} // if cpid
// back in parent process
This fires off gnuplot as I expect it should. I can see gnuplot consuming all the resources of one core as it normally does. The problem is that no graph appears on the screen.
So my question is, how do I start a child process, totally detach it from the console so it won't get any keystrokes and get the output of gnuplot to display?
i have a watchdog stop function placed inside the deconstructor of the process that i executed from my C++ program. Everytime i close using the "X" button on that process QT GUI, it will run thru the codes that i placed in the deconstructor. but when i try to do a Qprocesskill/close/terminate to kill the process in my C++ program, the codes in the deconstructors(of the process) are not being executed. Anyone knows whats wrong or have alternative methods to close the process? Thanks!!!
Btw im on linux.
No objects get torn down when the process abruptly exits with those functions. They're the equivalent to the C function exit(1). Try gracefully exiting the event loop of your QApplication::exec by calling QApplication::quit () which will exit the main event loop inside of exec and allow main to exit normally and allowing all objects that would normally destroy themselves at that point to do so.
Use std::signal to register the handlers for those signals (http://en.cppreference.com/w/cpp/utility/program/signal):
#include <csignal>
#include <iostream>
namespace
{
volatile std::sig_atomic_t gSignalStatus;
}
void signal_handler(int signal)
{
gSignalStatus = signal;
}
int main()
{
// Install a signal handler
std::signal(SIGINT, signal_handler);
std::cout << "SignalValue: " << gSignalStatus << '\n';
std::cout << "Sending signal " << SIGINT << '\n';
std::raise(SIGINT);
std::cout << "SignalValue: " << gSignalStatus << '\n';
}