In the following code, I create a toy class that has a thread which writes to a queue while the other thread reads from that queue and prints it to stdout. Now, in order to cleanly shutdown the system, I setup a handler for SIGINT. I am expecting the signal handler to set up the std::atomic<bool> variable stopFlag, which will lead threadB to push a poison pill (sentinel) on to the queue encountering which threadA will halt.
class TestClass
{
public:
TestClass();
~TestClass();
void shutDown();
TestClass(const TestClass&) = delete;
TestClass& operator=(const TestClass&) = delete;
private:
void init();
void postResults();
std::string getResult();
void processResults();
std::atomic<bool> stopFlag;
std::mutex outQueueMutex;
std::condition_variable outQueueConditionVariable;
std::queue<std::string> outQueue;
std::unique_ptr<std::thread> threadA;
std::unique_ptr<std::thread> threadB;
};
void TestClass::init()
{
threadA = std::make_unique<std::thread>(&TestClass::processResults, std::ref(*this));
threadB = std::make_unique<std::thread>(&TestClass::postResults, std::ref(*this));
}
TestClass::TestClass():
stopFlag(false)
{
init();
}
TestClass::~TestClass()
{
threadB->join();
}
void TestClass::postResults()
{
while(true)
{
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
std::string name = "ABCDEF";
{
std::unique_lock<std::mutex> lock(outQueueMutex);
outQueue.push(name);
outQueueConditionVariable.notify_one();
}
if(stopFlag)
{
/*For shutting down output thread*/
auto poisonPill = std::string();
{
std::unique_lock<std::mutex> lock(outQueueMutex);
outQueue.push(poisonPill);
outQueueConditionVariable.notify_one();
}
threadA->join();
break;
}
}
}
void TestClass::shutDown()
{
stopFlag = true;
}
std::string TestClass::getResult()
{
std::string result;
{
std::unique_lock<std::mutex> lock(outQueueMutex);
while(outQueue.empty())
{
outQueueConditionVariable.wait(lock);
}
result= outQueue.front();
outQueue.pop();
}
return result;
}
void TestClass::processResults()
{
while(true)
{
const auto result = getResult();
if(result.empty())
{
break;
}
std::cout << result << std::endl;
}
}
static void sigIntHandler(std::shared_ptr<TestClass> t, int)
{
t->shutDown();
}
static std::function<void(int)> handler;
int main()
{
auto testClass = std::make_shared<TestClass>();
handler = std::bind(sigIntHandler, testClass, std::placeholders::_1);
std::signal(SIGINT, [](int n){ handler(n);});
return 0;
}
I compiled this using gcc 5.2 using the -std=c++14 flag. On hitting Ctrl-C on my CentOS 7 machine, I get the following error,
terminate called after throwing an instance of 'std::system_error'
what(): Invalid argument
Aborted (core dumped)
Please help me understand what is going on.
What happens is that your main function exits immediately destroying global handler object and then testClass. Then the main thread gets blocked in TestClass::~TestClass. The signal handler ends up accessing already destroyed objects, which leads to the undefined behaviour.
The root cause is undefined object ownership due to shared pointers - you do not know what and when ends up destroying your objects.
A more general approach is to use another thread to handle all signals and block signals in all other threads. That signal handling thread then can call any functions upon receiving a signal.
You also do not need the smart pointers and function wrappers here at all.
Example:
class TestClass
{
public:
TestClass();
~TestClass();
void shutDown();
TestClass(const TestClass&) = delete;
TestClass& operator=(const TestClass&) = delete;
private:
void postResults();
std::string getResult();
void processResults();
std::mutex outQueueMutex;
std::condition_variable outQueueConditionVariable;
std::queue<std::string> outQueue;
bool stop = false;
std::thread threadA;
std::thread threadB;
};
TestClass::TestClass()
: threadA(std::thread(&TestClass::processResults, this))
, threadB(std::thread(&TestClass::postResults, this))
{}
TestClass::~TestClass() {
threadA.join();
threadB.join();
}
void TestClass::postResults() {
while(true) {
std::this_thread::sleep_for(std::chrono::milliseconds(2000));
std::string name = "ABCDEF";
{
std::unique_lock<std::mutex> lock(outQueueMutex);
if(stop)
return;
outQueue.push(name);
outQueueConditionVariable.notify_one();
}
}
}
void TestClass::shutDown() {
std::unique_lock<std::mutex> lock(outQueueMutex);
stop = true;
outQueueConditionVariable.notify_one();
}
std::string TestClass::getResult() {
std::string result;
{
std::unique_lock<std::mutex> lock(outQueueMutex);
while(!stop && outQueue.empty())
outQueueConditionVariable.wait(lock);
if(stop)
return result;
result= outQueue.front();
outQueue.pop();
}
return result;
}
void TestClass::processResults()
{
while(true) {
const auto result = getResult();
if(result.empty())
break;
std::cout << result << std::endl;
}
}
int main() {
// Block signals in all threads.
sigset_t sigset;
sigfillset(&sigset);
::pthread_sigmask(SIG_BLOCK, &sigset, nullptr);
TestClass testClass;
std::thread signal_thread([&testClass]() {
// Unblock signals in this thread only.
sigset_t sigset;
sigfillset(&sigset);
int signo = ::sigwaitinfo(&sigset, nullptr);
if(-1 == signo)
std::abort();
std::cout << "Received signal " << signo << '\n';
testClass.shutDown();
});
signal_thread.join();
}
On your platform this signal handler is invoked when a real SIGINT signal comes. The list of functions that can be invoked inside of this signal handler is rather limited and calling anything else leads to an undefined behavior.
Related
I'm using std::thread to launch threads. Also, I need stats for the worker thread available at /proc/[pid]/tasks/[tid]. I need tid to be able to monitor thread stats. I was wondering if there was a way to extract tid from the parent thread. I know that syscall gettid() from the worker returns its id, but I want the threadId from the master and not the slave. Is there a way to extract tid from the thread_id gor from std::thread.get_tid() ?
I believe there might be better ways of doing this, please suggest :)
UPDATE:
How can you get the Linux thread Id of a std::thread() this provides some information on getting tid from the worker, adds an overhead to the thread launch. For instance, std::thread t = std::thread(&wrapper); t.get_id() can be called from the launcher thread. I was/am looking if there was a to do the same thing from the main/launcher thread in a safe way.
All threads have a unique id:
std::thread::id this_id = std::this_thread::get_id();
You can store it in a variable when the program starts and it'll be accessible from the other threads.
I understand what you mean when you say parent thread, but even though one thread gave birth to another, they are siblings.
if you want the master thread to be able to get the /proc path to each worker thread, you could wrap the worker thread object in a class that, when it starts the actual thread, creates a path property that the master can later get.
An example:
#include <unistd.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <condition_variable>
#include <iostream>
#include <mutex>
#include <thread>
// A base class for thread object wrappers
class abstract_thread {
public:
abstract_thread() {}
abstract_thread(const abstract_thread&) = delete;
abstract_thread(abstract_thread&& rhs) :
m_th(std::move(rhs.m_th)), m_terminated(rhs.m_terminated), m_cv{}, m_mtx{} {}
abstract_thread& operator=(const abstract_thread&) = delete;
abstract_thread& operator=(abstract_thread&& rhs) {
terminate();
join();
m_th = std::move(rhs.m_th);
m_terminated = rhs.m_terminated;
return *this;
}
virtual ~abstract_thread() {
// make sure we don't destroy a running thread object
terminate();
join();
}
virtual void start() {
if(joinable())
throw std::runtime_error("thread already running");
else {
std::unique_lock<std::mutex> lock(m_mtx);
m_terminated = true;
// start thread and wait for it to signal that setup has been done
m_th = std::thread(&abstract_thread::proxy, this);
m_cv.wait(lock, [this] { return m_terminated == false; });
}
}
inline bool joinable() const { return m_th.joinable(); }
inline void join() {
if(joinable()) {
m_th.join();
}
}
inline void terminate() { m_terminated = true; }
inline bool terminated() const { return m_terminated; }
protected:
// override if thread specific setup needs to be done before start() returns
virtual void setup_in_thread() {}
// must be overridden in derived classes
virtual void execute() = 0;
private:
std::thread m_th{};
bool m_terminated{};
std::condition_variable m_cv{};
std::mutex m_mtx{};
void proxy() {
{
std::unique_lock<std::mutex> lock(m_mtx);
setup_in_thread(); // call setup function
m_terminated = false;
m_cv.notify_one();
}
execute(); // run thread code
}
};
// an abstract thread wrapper capable of returning its /proc path
class proc_path_thread : public abstract_thread {
public:
// function to call from master to get the path
const std::string& get_proc_path() const { return m_proc_path; }
protected:
void setup_in_thread() override {
m_proc_path =
std::move(std::string("/proc/")) + std::to_string(syscall(SYS_gettid));
}
private:
std::string m_proc_path{};
};
// two different thread wrapper classes. Just inherit proc_path_thread and implement
// "execute()". Loop until terminated() is true (or you're done with the work)
class AutoStartThread : public proc_path_thread {
public:
AutoStartThread() { start(); }
private:
void execute() override {
while(!terminated()) {
std::this_thread::sleep_for(std::chrono::milliseconds(500));
std::cout << std::this_thread::get_id() << " AutoStartThread running\n";
}
}
};
class ManualStartThread : public proc_path_thread {
void execute() override {
std::this_thread::sleep_for(std::chrono::milliseconds(100));
std::cout << std::this_thread::get_id() << " ManualStartThread running\n";
std::this_thread::sleep_for(std::chrono::milliseconds(100));
}
};
int main() {
AutoStartThread a;
std::cout << a.get_proc_path() << "\t// AutoStartThread, will have path\n";
ManualStartThread b;
std::cout << b.get_proc_path()
<< "\t// ManualStartThread not started, no path\n";
b.start();
std::cout << b.get_proc_path()
<< "\t// ManualStartThread will now have a path\n";
b.join();
std::this_thread::sleep_for(std::chrono::milliseconds(1500));
// terminate() + join() is called automatically when abstract_thread descendants
// goes out of scope:
//
// a.terminate();
// a.join();
}
Possible output:
/proc/38207 // AutoStartThread, will have path
// ManualStartThread not started, no path
/proc/38208 // ManualStartThread will now have a path
139642064209664 ManualStartThread running
139642072602368 AutoStartThread running
139642072602368 AutoStartThread running
139642072602368 AutoStartThread running
139642072602368 AutoStartThread running
You can launch the thread through a function whose first task will be to message it's id, e.g., either classically using mutexes and condvars:
#include <stdio.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <unistd.h>
struct tid_msg{
pthread_mutex_t mx;
pthread_cond_t cond;
pid_t tid;
};
void *thr(void*A)
{
struct tid_msg *msg = A;
pid_t tid = syscall(SYS_gettid);
pthread_mutex_lock(&msg->mx);
msg->tid = tid;
pthread_mutex_unlock(&msg->mx);
pthread_cond_signal(&msg->cond);
printf("my tid=%lu\n", (long unsigned)tid);
return 0;
}
int main()
{
struct tid_msg msg = { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, -1 };
pthread_t ptid;
pthread_create(&ptid,0,thr,&msg);
pthread_mutex_lock(&msg.mx);
while(-1==msg.tid) pthread_cond_wait(&msg.cond,&msg.mx);
pthread_mutex_unlock(&msg.mx);
printf("their tid=%lu\n", (long unsigned)msg.tid);
pthread_join(ptid,0);
}
or simply via an atomic variable (relaxed memory ordering should be fine here,
but you can play it safe and use the sequentially consistent default):
#include <stdio.h>
#include <pthread.h>
#include <sys/syscall.h>
#include <unistd.h>
#include <stdatomic.h>
void *thr(void*A)
{
_Atomic pid_t *tidp = A;
pid_t tid;
tid = syscall(SYS_gettid);
atomic_store_explicit(tidp, tid, memory_order_relaxed);
printf("my tid=%lu\n", (long unsigned)tid);
return 0;
}
int main()
{
_Atomic pid_t tid=-1;
pthread_t ptid;
pthread_create(&ptid,0,thr,&tid);
while(-1==atomic_load_explicit(&tid,memory_order_relaxed)) ;
printf("their tid=%lu\n", (long unsigned)tid);
pthread_join(ptid,0);
}
My simplified question
I read this thread and I am trying to delete the io_service object. I do this
m_IO.stop();
m_IO.~io_service();
m_IO is an object of boost::asio::io_service. I found that my thread was blocked by m_IO.~io_service(); How can I delete io_service?
My Complete question
I am making a daily timer by using boost io_service and deadline timer. The problem is when I want to delete my daily timer, my thread will disappear when it try to delete boost io_service.
main.cpp
int main()
{
myDailyTimer* pTimer = new myDailyTimer;
// do something
delete pTimer;
return 0;
}
I set break points in myDailyTimer.cpp::int i = 0; and myDailyTimer.cpp::int j = 0; and main::return 0; My main thread can reach int i = 0;, My timer thread cannot reach int j = 0;, My main thread cannot reach return 0;.
I found the my main thread will disappear when it try to delete boost::asio::io_service object. How to solve this problem? Am I using boost::asio::io_service in a wrong way?
myDailyTimer.h
class myDailyTimerInterface
{
public:
myDailyTimerInterface(){}
~myDailyTimerInterface(){}
virtual void TimerCallback(int nTimerID) = 0;
};
class myDailyTimer :
public myThread
{
public:
boost::asio::io_service m_IO;
boost::asio::deadline_timer * m_pTimer;
tm m_tmSpecificTime;
std::string m_strSpecificTime;
int m_nTimerID;
myDailyTimerInterface* m_pParent;
public:
myDailyTimer();
~myDailyTimer();
void SetTime(tm strIN, int nID); // msec
void TimerCallback();
//Override
void ThreadMain();
protected:
std::string MakeStringSpecificTime();
void AddOneDay();
};
myDailyTimer.cpp
myDailyTimer::myDailyTimer()
{
m_pTimer = 0;
m_strSpecificTime = "";
}
myDailyTimer::~myDailyTimer()
{
EndThread();
if (m_pTimer != 0)
{
m_pTimer->cancel();
delete m_pTimer;
}
m_IO.stop();
m_IO.~io_service();
int i = 0;
i++;
}
void myDailyTimer::SetTime(tm tmIN, int nID) // msec
{
if (m_pTimer != 0)
{
m_pTimer->cancel();
delete m_pTimer;
}
m_tmSpecificTime = tmIN;
m_strSpecificTime = MakeStringSpecificTime();
m_nTimerID = nID;
m_pTimer = new boost::asio::deadline_timer(m_IO, boost::posix_time::time_from_string(m_strSpecificTime));
m_pTimer->async_wait(boost::bind(&myDailyTimer::TimerCallback, this));
myThread::Start();
}
std::string myDailyTimer::MakeStringSpecificTime()
{
time_t localTime;
localTime = mktime(&m_tmSpecificTime); // time is GMT local
struct tm * ptm = gmtime(&localTime); // convert time to GMT +0
char veccNextTime[64];
memset(veccNextTime, 0, sizeof(veccNextTime));
sprintf(veccNextTime, "%d-%02d-%02d %02d:%02d:%02d.000",
ptm->tm_year + 1900, ptm->tm_mon + 1, ptm->tm_mday,
ptm->tm_hour, ptm->tm_min, ptm->tm_sec);
std::string strTemp(veccNextTime);
return strTemp;
}
void myDailyTimer::AddOneDay()
{
m_tmSpecificTime.tm_mday += 1;
mktime(&m_tmSpecificTime); /* normalize result */
}
void myDailyTimer::TimerCallback()
{
if (m_pParent != 0)
m_pParent->TimerCallback(m_nTimerID);
//m_timer->expires_from_now(boost::posix_time::milliseconds(m_nTimerDuration));
AddOneDay();
m_strSpecificTime = MakeStringSpecificTime();
m_pTimer->expires_at(boost::posix_time::time_from_string(m_strSpecificTime));
m_pTimer->async_wait(boost::bind(&myDailyTimer::TimerCallback, this));
}
//Override
void myDailyTimer::ThreadMain()
{
while (!IsEndThread())
m_IO.run();
int j = 0;
j++;
}
As Dan MaĊĦek mentioned, explicitly calling the destructor isn't a good pattern here. The standard way to stop an io_service is to stop every "work" that is pending and then wait for io_service::run function to return. Also, to prevent the io_service::run function from returning prematurely, it is a good idea to create an instance of io_service::work object.
Hope you'll be able to modify this example to your use case:
namespace asio = boost::asio;
class MyTimer {
using Clock = std::chrono::steady_clock;
public:
MyTimer(Clock::duration duration)
: _work(_ios)
, _timer(_ios)
, _thread([this] { _ios.run(); })
{
_ios.post([this, duration] { start(duration); });
}
~MyTimer() {
_ios.post([this] { stop(); });
_thread.join();
}
private:
void start(Clock::duration duration) {
_timer.expires_from_now(duration);
_timer.async_wait([this](boost::system::error_code) {
// NOTE: Be careful here as this is run from inside
// the thread.
if (!_work) {
// Already stopped.
std::cout << "Stopped" << std::endl;
return;
}
std::cout << "Timer fired" << std::endl;
});
}
void stop() {
_work.reset();
_timer.cancel();
}
private:
asio::io_service _ios;
boost::optional<asio::io_service::work> _work;
asio::steady_timer _timer;
std::thread _thread;
};
int main() {
auto* my_timer = new MyTimer(std::chrono::seconds(1));
delete my_timer;
return 0;
}
I have experience with threads in Java but want to learn how to use them in C++11. I tried to make a simple threadpool, where threads are created once and can be asked to execute tasks.
#include <thread>
#include <iostream>
#define NUM_THREADS 2
class Worker
{
public:
Worker(): m_running(false), m_hasData(false)
{
};
~Worker() {};
void execute()
{
m_running = true;
while(m_running)
{
if(m_hasData)
{
m_system();
}
m_hasData = false;
}
};
void stop()
{
m_running = false;
};
void setSystem(const std::function<void()>& system)
{
m_system = system;
m_hasData = true;
};
bool isIdle() const
{
return !m_hasData;
};
private:
bool m_running;
std::function<void()> m_system;
bool m_hasData;
};
class ThreadPool
{
public:
ThreadPool()
{
for(int i = 0; i < NUM_THREADS; ++i)
{
m_threads[i] = std::thread(&Worker::execute, &m_workers[i]);
}
};
~ThreadPool()
{
for(int i = 0; i < NUM_THREADS; ++i)
{
std::cout << "Stopping " << i << std::endl;
m_workers[i].stop();
m_threads[i].join();
}
};
void execute(const std::function<void()>& system)
{
// Finds the first non-idle worker - not really great but just for testing
for(int i = 0; i < NUM_THREADS; ++i)
{
if(m_workers[i].isIdle())
{
m_workers[i].setSystem(system);
return;
}
}
};
private:
Worker m_workers[NUM_THREADS];
std::thread m_threads[NUM_THREADS];
};
void print(void* in, void* out)
{
char** in_c = (char**)in;
printf("%s\n", *in_c);
}
int main(int argc, const char * argv[]) {
ThreadPool pool;
const char* test_c = "hello_world";
pool.execute([&]() { print(&test_c, nullptr); });
}
The output of this is:
hello_world
Stopping 0
After that, the main thread halts, because it's waiting for the first thread to join (in the destructor of the ThreadPool). For some reason, the m_running variable of the workers is not set to false, which keeps the application running indefinitely.
In Worker::stop the member m_running is written in the main thread, while it is read in execute in a different thread. This is undefined behavior. You need to protect read/write access from different threads. In this case I would recommend using std::atomic<bool> for m_running.
Edit: the same holds for m_hasData.
I have a class which is creating a thread and stores it. While doing some stuff this thread can notice some error, notify the class and interrupt it self.
class foo {
public:
enum mode {
run=0,
booboo,
stop
};
foo() {
th_ = boost::thread(boost::bind(&foo::bar, this));
mode_ = run;
}
~foo() {
stop();
}
void stop() {
mode_ = stop;
th_.join();
}
void bar {
for(;;) {
if(mode_ == stop)
return;
if(error) {
mode_ = booboo;
th_.interrupt();
// the sleep is the interruption point
boost::this_thread::sleep_for(boost::chrono::nanoseconds(0));
}
// do some stuff
}
}
private:
boost::thread th_;
mode mode_;
};
According to boost::thread.interrupt there is no indication that this won't work. If I understand it right, interrupt will mark the thread to interrupt it on the next interruption_point which is in my case the call of sleep_for.
On my machine and OS, it is working, so my question is, is it safe to do so?
I have a class defined like this: This is not all complete and probably won't compile.
class Server
{
public:
Server();
~Server();
class Worker
{
public:
Worker(Server& server) : _server(server) { }
~Worker() { }
void Run() { }
void Stop() { }
private:
Server& _server;
}
void Run()
{
while(true) {
// do work
}
}
void Stop()
{
// How do I stop the thread?
}
private:
std::vector<Worker> _workers;
};
My question is, how do I initialize the workers array passing in the outer class named Server.
What I want is a vector of worker threads. Each worker thread has it's own state but can access some other shared data (not shown). Also, how do I create the threads. Should they be created when the class object is first created or externally from a thread_group.
Also, how do I go about shutting down the threads cleanly and safely?
EDIT:
It seems that I can initialize Worker like this:
Server::Server(int thread_count)
: _workers(thread_count), Worker(*this)), _thread_count(thread_count) { }
And I'm currently doing this in Server::Run to create the threads.
boost::thread_group _threads; // a Server member variable
Server::Run(){
for (int i = 0; i < _thread_count; i++)
_threads.create_thread(boost::bind(&Server::Worker::Run, _workers(i)));
// main thread.
while(1) {
// Do stuff
}
_threads.join_all();
}
Does anyone see any problems with this?
And how about safe shutdown?
EDIT:
One problem I have found with it is that the Worker objects don't seem to get constructed!
oops. Yes they do I need a copy constructor on the Worker class.
But oddly, creating the threads results in the copy constructor for Worker being called multiple times.
I have done it with pure WINAPI, look:
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <vector>
using namespace std;
class Server
{
public:
class Worker
{
int m_id;
DWORD m_threadId;
HANDLE m_threadHandle;
bool m_active;
friend Server;
public:
Worker (int id)
{
m_id = id;
m_threadId = 0;
m_threadHandle = 0;
m_active = true;
}
static DWORD WINAPI Run (LPVOID lpParam)
{
Worker* p = (Worker*) lpParam; // it's needed because of the static modifier
while (p->m_active)
{
printf ("I'm a thread #%i\n", p->m_id);
Sleep (1000);
}
return 0;
}
void Stop ()
{
m_active = false;
}
};
Server ()
{
m_workers = new vector <Worker*> ();
m_count = 0;
}
~Server ()
{
delete m_workers;
}
void Run ()
{
puts ("Server is run");
}
void Stop ()
{
while (m_count > 0)
RemoveWorker ();
puts ("Server has been stopped");
}
void AddWorker ()
{
HANDLE h;
DWORD threadId;
Worker* n = new Worker (m_count ++);
m_workers->push_back (n);
h = CreateThread (NULL, 0, Worker::Run, (VOID*) n, CREATE_SUSPENDED, &threadId);
n->m_threadHandle = h;
n->m_threadId = threadId;
ResumeThread (h);
}
void RemoveWorker ()
{
HANDLE h;
DWORD threadId;
if (m_count <= 0)
return;
Worker* n = m_workers->at (m_count - 1);
m_workers->pop_back ();
n->Stop ();
TerminateThread (n->m_threadHandle, 0);
m_count --;
delete n;
}
private:
int m_count;
vector <Worker*>* m_workers;
};
int main (void)
{
Server a;
int com = 1;
a.Run ();
while (com)
{
if (kbhit ())
{
switch (getch ())
{
case 27: // escape key code
com = 0;
break;
case 'a': // add worker
a.AddWorker ();
break;
case 'r': // remove worker
a.RemoveWorker ();
break;
}
}
}
a.Stop ();
return 0;
}
There are no synchronization code here, because I haven't enougth time to do it... But I wish it will help you =)
Have you looked at boost asio at all? It looks like it could be a good fit for what you are trying to do. Additionally you can call boost asio's io_service's run (similar to your Run method) from many threads i.e. you can process your IO in many threads. Also of interest could be http://think-async.com/Asio/Recipes for an asio based thread-pool.
Have a look at the asio examples. Perhaps they offer an alternative way of handling what you are trying to do. Esp. have a look at how a clean shutdown is accomplished.