Safely interrupt C++11 blocking operation - c++

I have a std::thread that uses Boost's asio to read from a serial port:
std::atomic<bool> quit(false);
void serialThread()
{
try
{
asio::io_service io;
asio::serial_port port(io);
port.open("COM9"); // Yeay no port enumeration support!
port.set_option(asio::serial_port_base::baud_rate(9600));
while (!quit)
{
asio::streambuf buf;
asio::read_until(port, buf, "\n");
auto it = asio::buffers_begin(buf.data());
string line(it, it + buf.size());
doStuffWithLine(line);
}
}
catch (std::exception e)
{
cout << "Serial thread error: " << e.what() << endl;
}
}
void SetupSignals()
{
// Arrange it so that `quit = true;` happens when Ctrl-C is pressed.
}
int main(int argc, char *argv[])
{
SetupSignals();
thread st(serialThread);
st.join();
return 0;
}
When I press Ctrl-C I want to cleanly exit the thread, so that all destructors are called appropriately (some drivers on Windows hate it if you don't close their resources properly).
Unfortunately as you can see, the current code blocks in read_until() so when you press Ctrl-C nothing will happen until a new line of text is received.
One solution is to use polling, something like this:
asio::async_read_until(port, buf, "\n", ...);
while (!quit)
io.poll();
But I'd rather not use polling. It is pretty inelegant. The only solution I can currently see is to have a std::condition_variable quitOrIoFinished that is triggered either when quit is set to true, or when the read finishes. But I didn't write asio so I can't give it a condition variable to wait on.
Is there any clean sane solution? In Go I would just use a select to wait on multiple channels, where one of them is a quit channel. I can't see a similar solution in C++ though.

Use an asio::signal_set to await the INT signal (control-C tends to send interrupt).
When it arrives, simply call cancel() on your IO objects with pending asynchronous operations. They will return with error_code equal to boost::asio::error::operation_aborted.
Now, if you have a io_service::work object, destruct it and the all threads running io_service::run() will return, so you can join them.
Note Take care of synchronizing access to your IO objects (e.g. when you invoke cancel() on them) because these objects are not thread-safe, unlike io_service and strand.

Related

boost::asio::io_service.post() background thread memory usage

I want to run boost::asio::io_service.run() in a background thread. So when I need it post() func into.
This is main func:
int main(int /*argc*/, char** /*argv*/)
{
std::string message = "hello";
logg = new logger_client(filename,ip,13666);
logg->start();
while (true)
logg->add_string(message);
return 0;
}
And some relevant funcs from logger_client:
std::auto_ptr<boost::asio::io_service::work> work;
logger_client::logger_client(std::string& filename,std::string& ip, uint16_t port) : work(new boost::asio::io_service::work(io_service))
{
}
void logger_client::start()
{
ios_thread = new boost::thread(boost::bind(&io_service.run,&io_service));
}
void print_nothing()
{
printf("%s\n","lie");
}
void logger_client::add_string(std::string& message)
{
io_service.post(boost::bind(print_nothing));
//io_service.post(strand->wrap(boost::bind(&logger_client::add_string_imp,this,message)));
//io_service.run();
}
When i run this, my program eats 2Gb less than a minute. If i remove endless work and change to this:
void logger_client::add_string(std::string& message)
{
io_service.post(boost::bind(print_nothing));
//io_service.post(strand->wrap(boost::bind(&logger_client::add_string_imp,this,message)));
io_service.run();
}
Program works just fine. But I don't want to invoke async operations on this (main) thread. What am i doing wrong?
UPDATE
I added sleep(1sec) in while(true) loop and memory is no longer growing. But this is not a solution. Because if I call run() after post() (i.e. use main thread for processing handles) and even add five more threads with while(true) loops memory is not growing. So why main thread is so much better than newly created? I also tried thread pool for io_service::run - did not help.
io_service.run will exit unless there are pending operations.
Therefore, your ios_thread will exit immediately.
The solution is to use io_service::work.
In addition, endless loop spam like this
while (true)
logg->add_string(message);
is not a good idea, maybe add some sleep(), to slow it down a bit and keep it under control.

How do I send a SIGTERM or SIGINT signal to the server in the boost HTML3 example?

I am using the HTML Server 3 example from boost as my learning tool (http://www.boost.org/doc/libs/1_53_0/doc/html/boost_asio/examples.html#boost_asio.examples.http_server_3) for asynchronous message handling.
I have taken the example, and turned it into a library with a server object I can instantiate in my programs. The only thing I have done to the above example is remove the main.cpp and compile it as a library. And it works to the extend that I can instantiate the server object in my code, and pass messages to it from the command line.
Where I am struggling is how to terminate the server gracefully. From the sample code I see this:
server::server(const std::string& address, const std::string& port,
std::size_t thread_pool_size,
Handler &handler)
: thread_pool_size_(thread_pool_size),
signals_(io_service_),
acceptor_(io_service_),
new_connection_(),
request_handler_(handler)
{
// Register to handle the signals that indicate when the server should exit.
// It is safe to register for the same signal multiple times in a program,
// provided all registration for the specified signal is made through Asio.
signals_.add(SIGINT);
signals_.add(SIGTERM);
signals_.async_wait(boost::bind(&server::handle_stop, this));
So an asynchronous thread is set up to listen for signals and respond to them
I have implemented this server object in a thread in my program as follows:
class ServerWorker
{
public:
ServerWorker(std::string theHost, std::string thePort)
{
Host = theHost;
Port = thePort;
}
void Start()
{
try
{
MYRequestHandler handler;
int nCores = boost::thread::hardware_concurrency();
server *mServer = new server(Host, Port, nCores, handler);
svr->run();
}
catch(std::exception &e) { /* do something */ }
}
void Stop()
{
mServer->stop(); // this should raise a signal and send it to the server
// but don't know how to do it
}
private:
std::string Host;
std::string Port;
server *mServer;
};
TEST(BSGT_LBSSERVER_STRESS, BSGT_SINGLETON)
{
// Launch as server on a new thread
ServerWorker sw(BSGT_DEFAULT_IPADDRESS, BSGT_DEFAULT_PORT_STR);
boost::function<void()> th_func = boost::bind(&ServerWorker::Start, &sw);
boost::thread swThread = boost::thread(th_func);
// DO SOMETHING
// How do I signal the server in the swThread to stop?
}
How do I implement the stop() method on the server object to send the signal to itself? I have tried:
1) raise(SIGTERM) - kills the whole program
2) raise(SIGINT) - kills the whole program
raise() is appropriate for having a process signal itself.
void ServerWorker::Stop()
{
std::raise(SIGTERM);
}
Be aware that raise() is asynchronous. It will issue the signal and return immediately. Hence, control may continue before the io_service processes the enqueued SignalHandler.
void run_server()
{
// Launch as server on a new thread
ServerWorker server_worker(...);
boost::thread worker_thread([&server_worker]() { server_worker.Start(); });
...
// Raises SIGTERM. May return before io_service is stopped.
server_worker.Stop();
// Need to synchronize with worker_thread. The `worker_thread` may still be
// in `ServerWorker::Start()` which would go out of scope. Additionally,
// the `worker_thread` is joinable, so its destructor may invoke
// `std::terminate()`.
}
Here is a minimal example demonstrating using Boost.Asio signal handling, raise(), and synchronization:
#include <cassert>
#include <csignal>
#include <iostream>
#include <thread>
#include <boost/asio.hpp>
int main()
{
boost::asio::io_service io_service;
// Prevent io_service from running out of work.
boost::asio::io_service::work work(io_service);
// Boost.Asio will register an internal handler for SIGTERM.
boost::asio::signal_set signal_set(io_service, SIGTERM);
signal_set.async_wait(
[&io_service](
const boost::system::error_code& error,
int signal_number)
{
std::cout << "Got signal " << signal_number << "; "
"stopping io_service." << std::endl;
io_service.stop();
});
// Raise SIGTERM.
std::raise(SIGTERM);
// By the time raise() returns, Boost.Asio has handled SIGTERM with its
// own internal handler, queuing it internally. At this point, Boost.Asio
// is ready to dispatch this notification to a user signal handler
// (i.e. those provided to signal_set.async_wait()) within the
// io_service event loop.
std::cout << "io_service stopped? " << io_service.stopped() << std::endl;
assert(false == io_service.stopped());
// Initiate thread that will run the io_service. This will invoke
// the queued handler that is ready for completion.
std::thread work_thread([&io_service]() { io_service.run(); });
// Synchornize on the work_thread. Letting it run to completion.
work_thread.join();
// The io_service has been explicitly stopped in the async_wait
// handler.
std::cout << "io_service stopped? " << io_service.stopped() << std::endl;
assert(true == io_service.stopped());
}
Output:
io_service stopped? 0
Got signal 15; stopping io_service.
io_service stopped? 1

boost asio - session thread does not end

I use boost asio to handle a session per thread like this:
Server::Server(ba::io_service& ioService, int port): ioService_(ioService), port_(port)
{
ba::ip::tcp::acceptor acceptor(ioService_, ba::ip::tcp::endpoint(ba::ip::tcp::v4(), port_));
for (;;)
{
socket_ptr sock(new ba::ip::tcp::socket(ioService_));
acceptor.accept(*sock);
boost::thread thread(boost::bind(&Server::Session, this, sock));
}
}
void Server::Session(socket_ptr sock)
{
const int max_length = 1024;
try
{
char buffer[256] = "";
// HandleRequest() function performs async operations
if (HandleHandshake(sock, buffer))
HandleRequest(sock, buffer);
ioService_.run();
}
catch (std::exception& e)
{
std::cerr << "Exception in thread: " << e.what() << "\n";
}
std::cout << "Session thread ended \r\n"; // THIS LINE IS NEVER REACHED
}
In Server::Session() I do at some point async io using async_read_some() and async_write() functions.
All works well and in order for this to work I have to have a call to ioService_.run() inside my spawn thread otherwise Server::Session() function exits and it does not process the required io work.
The problem is that ioService_.run() called from my thread will lead for the thread not to exit at all because in the meantime other requests come to my listening server socket.
What I end up with is threads starting and processing for now sessions but never releasing resources (ending). Is it possible to use only one boost::asio::io_service when using this approach ?
I believe you are looking for run_one() or poll_one() this will allow you to have the thread either execute a ready handler (poll) or wait for a handler (run). By only handling one, you can pick how many to execute before exiting your thread. As opposed to run() which executes all the handlers until the io_service is stopped. Where as poll() would stop after it handled all the ones that are currently ready.
The way I structured handling connection here was bad.
There is quite a good video presentation about how to design your asio server bellow(made by asio creator)
Thinking Asynchronously: Designing Applications with Boost Asio

gSoap: how to gracefully shutdown the webservice application?

I'm using gSoap to write a webservice. It's running as a console application. In all gSoap examples I see, that requests are dispatched in infinite loop like for(;;;) even in multi-threaded version.
But how can I make my webservice to terminate gracefully when, say, user presses space on the console?
Preferably:
stop accepting new connections;
Serve existing ones;
Exit from application
The only solution I came up so far is using timeouts
soap->recv_timeout = 20;
soap->send_timeout = 20;
soap->connect_timeout = 5;
soap->accept_timeout = 5;
Then all blocking functions return periodically. But this is not ideal for me, because I want to be able to terminate the app quickly even if there is an ongoing transmission, but at the same time, don't want to compromise reliability on a slow/flaky connection (it's an embedded device connected via GPRS).
The section 7.2.4 How to Create a Multi-Threaded Stand-Alone Service in the documentation has example code for writing an accept loop. You need to write your own accept loop and add signal handling so it responds to Ctrl-C.
stop accepting new connections:
Leave the loop so you stop calling accept.
Serve existing ones:
The threads need to inform you when they are finished, so you can exit when the number of active clients is zero. (boost::thead_group has a join_all which does exactly that.)
Exit from application:
What you need to do is register signal handler so when you terminate your application using Ctrl + C, it calls you registered function where you can gracefully terminates.
e.g
class gsoap_test {
public:
void start() {
running_ = true;
while(running_) {
//gsoap threads
}
//stop and cleanup
}
void stop() {
running_ = false;
}
private:
bool running_;
};
//global variable
gsoap_test gsoap;
void sighandler(int sig)
{
std::cout<< "Signal caught..." << std::endl;
//Stop gracefully here
gsoap.stop();
exit(0);
}
int main(int argc, char** argv) {
//register signal
signal(SIGABRT, &sighandler);
signal(SIGTERM, &sighandler);
signal(SIGINT, &sighandler);
gsoap.start();
return EXIT_SUCCESS;
}

Sockets and multithreading

I have an interesting (to me) problem... There are two threads, one for capturing data from std input and sending it through socket to server, and another one which receives data from blocking socket. So, when there's no reply from server, recv() call waits indefenitely, right? But instead of blocking only its calling thread, it blocks the overall process! Why this thing occurs?
boost::mutex nvtMutex;
boost::mutex strMutex;
boost::mutex quitMutex;
bool quit = false;
void *processServerOutput(void *arg)
{
NVT *nvt = (NVT*)arg;
while(1)
{
// Lock the quitMutex before trying to access to quit variable
quitMutex.lock();
if(quit)
{
quitMutex.unlock();
pthread_exit(NULL);
}
else
quitMutex.unlock();
// Receive output from server
nvtMutex.lock();
nvt->receive();
cout << Util::Instance()->iconv("koi8-r", "utf-8", nvt->getOutBuffer());
nvtMutex.unlock();
// Delay
sleep(1);
}
}
void *processUserInput(void *arg)
{
NVT *nvt = (NVT*)arg;
while(1)
{
// Get user's input
//cin.getline(str, 1023);
sleep(3);
strcpy(str, "hello");
// If we type 'quit', exit from thread
if(strcmp(str, "quit") == 0)
{
// Lock quit variable before trying to modify it
quitMutex.lock();
quit = true;
quitMutex.unlock();
// Exit from thread
pthread_exit(NULL);
}
// Send the input to server
nvtMutex.lock();
nvt->writeUserCommand(Util::Instance()->iconv("utf-8", "koi8-r", str));
nvt->send();
nvtMutex.unlock();
}
}
You are holding the nvtMutex inside the call to NVT::recv. Since both threads need to lock the mutex to make it through an iteration, until NVT::recv returns the other thread can't progress.
Without knowing the details of this NVT class, it's impossible to know if you can safely unlock the mutex before calling NVT::recv or if this class does not provide the proper thread safety you need.
If your code is implemented correctly, recv blocks only the thread that invokes it.
If this isn't the case for you, show the minimal code sample that demonstrates the problem.