It is a part of a larger application, a simple timer thread, which works correctly before an attempt to finish it:
boost::asio::io_service io_service;
shared_ptr<thread> loop;
// it is not initialised here, just shows the idea
boost::asio::deadline_timer timer(io_service, interval);
void Timer::spin() {
loop = make_shared<thread>(&Timer::run, this);
}
void Timer::unspin() {
io_service.stop();
loop.get()->join();
}
void run() {
timer.async_wait(bind(&Timer::callbackWrapper, this, _1));
// restart
io_service.run();
}
The thread created in spin is in theory terminated and joined in unspin(). In case when the application ends with join() commented out, there in an error message
terminate called without an active exception
which, if I "decrypted" it well, means "main thread finished when some other threads are still running" (I do not know the C++ lingo.)
If, in turn, unspin() is called, the following spotty error message may show:
terminate called after throwing an instance of 'std::system_error'
what(): Invalid argument
which is most probably thrown by thread.join(). The problem is, I searched around Stackexchange, but could not explain the other message. I realise that the problem can be outside the small fragment of code (the application is rather large, so I do not include it). But even if it is so, I would just ask for the meaning of the second error message and its possible causes.
In my particular case, the exception was thrown because the thread had already been joined. Check joinable before joining.
The possible causes for something to throw std::system_error (with EINVAL, as here, or with some other value) are numerous.
You could either:
std::system_error on cppreference.com, orThese messages aren't cryptic per se, they're just indirect oweing to the way the whole C++ ecosystem works. Could it have been designed to call some specific "terminate" function solely reserved for the case where you forget to join a thread? Sure.
But that would be really unwieldy, bulking up the size of the runtime module, for not really any gain. As you write more code you will gain experience and start just remembering or "feeling" what sort of things can cause what sort of problems. Anything about std::system_error or std::terminate in multi-threaded code is almost certainly something to do with improper handling of said threads. You just get to know that after a while.
In this case you can memorise the two following explanations:
terminate called without an active exception
Something called std::terminate directly. Again, you can search for utterances of this in library documentation and find out possible causes that relate to your code.
terminate called after throwing an instance of 'std::system_error'
An exception was thrown, but you have no try/catch in your program that caught it, so std::terminate was invoked by the exceptions system. Again, you can research what features you're using can throw std::system_error, and also consider adding some exception safety to your code while you're at it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With