Boost logo

Boost Users :

Subject: Re: [Boost-users] [asio] Error running as Windows service; runs fine from console
From: Evan Burkitt (eburkitt_at_[hidden])
Date: 2010-09-16 00:42:31


"Igor R" <boost.lists_at_[hidden]> wrote in message
news:AANLkTi=KbEKrO62tK3xeULrKivbNfLs47=2+6KusF21R_at_mail.gmail.com...
>> my call to boost::asio::ip::tcp::acceptor::async_accept() immediately
>> calls the passed
>> accept handler to report error 995: "The I/O operation has been aborted
>> because of either a thread exit or an application request". This occurs
>> even
>> when I run the service under the same account as the logged-in user.
>
> Maybe it's just a coincidence that the issue appears in service mode
> only. Ensure that the thread where you call async_accept() doesn't
> exit until the handler gets called.

I think this is the problem.

My application is written to run on the console as nearly as possible the
same as it runs as a service. It starts by creating an instance of a
task_scheduler class, then calling that instance's start() member function:
void task_scheduler::start(void)
{
...
 svr_.reset(new server(port, num_threads));
 svr_->start();
}

The server ctor looks like this:
server::server(short port, std::size_t threads)
: acceptor_(io_service_, ip::tcp::endpoint(ip::tcp::v4(), port))
//tcp::acceptor
, connection_(new connection(io_service_))
, thread_pool_size_(threads)
{
 acceptor_.async_accept(connection_->socket(),
         boost::bind(&server::handle_accept, this,
            boost::asio::placeholders::error));
}

and server::start() looks like this:

void server::start(void)
{
 if (0 == threads_.size())
 {
  threads_.size_controller().resize(thread_pool_size_);
  for (std::size_t i = 0; i < threads_.size(); ++i)
  {
   threads_.schedule(boost::bind(&boost::asio::io_service::run,
&io_service_));
  }
 } //if
}

Actual input (and thus, a call to server::handle_accept()) may not start for
a long time after the above is executed.

When the program runs on the console, the main thread calls
task_scheduler::start(), waits for input from stdin, then begins shutting
things down. When it's run as a service, the Windows service manager calls
task_scheduler::start() on a thread that apparently ends once
task_scheduler::start() returns. Since the server was created (and
tcp::acceptor::async_accept() called) on that thread, its termination is the
source of the error.

Based on your advice I'm going to have to cause the creation of the server
instance to be done somewhere other than during the service manager's call
to start the service.

I'll save my most effusive thanks until I've had the chance to try this :)
but I greatly appreciate your mention of this quirk of asio's. This is not
something I was likely to discover on my own.

-evan


Boost-users list run by williamkempf at hotmail.com, kalb at libertysoft.com, bjorn.karlsson at readsoft.com, gregod at cs.rpi.edu, wekempf at cox.net