[asio] Error running as Windows service; runs fine from console
I have a Windows application that uses ASIO to implement a server that listens on a TCP port. When I run it from the console it starts and operates without error. When I start the same application as a Windows service (it's written to be run either way) 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. I know I'm a bit sketchy with the details of my implementation, but I think this is at least as likely to be some Windows weirdness as an ASIO problem per se. I'm hoping someone else has encountered and fixed this problem before. Thanks. -evan
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.
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.
By the way, I guess you use different threading models in console and service modes. In console mode it can be just: int main() { // prepare i/o object, call async_accept() etc io_service_.run() } But how and where do you run your io_service in service mode? Probably the answer to this question would explain why you get the error.
"Igor R"
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
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.
Maybe you can just move the all acceptor stuff to server::start().
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.
Maybe you can just move the all acceptor stuff to server::start(). That won't work; server::start() gets called on the service manager thread, too, immediately after the ctor. The solution is going to require moving the creation of the server instance to where it can be done on a persistent
"Igor R"
That won't work; server::start() gets called on the service manager thread, too, immediately after the ctor.
Merely move async_accept to another function, then call io_service_.post(...). This way async_accept will be performed on an io_service thread.
AFAIK Windows services by default do not have network access rights. They run in a special "local" service account that does not allow access to the network. What I don't know is if "network" means any network including tcp/ip here, or if "network" means only windows networking. Try running your service under an interactive account and see if the problem persists. I'm sure there's more info in the appropriate windows newsgroups on this topic. Regards Hajo On 15.09.2010 06:10, Evan Burkitt wrote:
I have a Windows application that uses ASIO to implement a server that listens on a TCP port. When I run it from the console it starts and operates without error. When I start the same application as a Windows service (it's written to be run either way) 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.
I know I'm a bit sketchy with the details of my implementation, but I think this is at least as likely to be some Windows weirdness as an ASIO problem per se. I'm hoping someone else has encountered and fixed this problem before.
Thanks.
-evan
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org http://lists.boost.org/mailman/listinfo.cgi/boost-users
On 09/14/2010 11:10 PM, Evan Burkitt wrote:
I have a Windows application that uses ASIO to implement a server that listens on a TCP port. When I run it from the console it starts and operates without error. When I start the same application as a Windows service (it's written to be run either way) my call to[...] I know I'm a bit sketchy with the details of my implementation, but I think this is at least as likely to be some Windows weirdness as an ASIO problem per se. I'm hoping someone else has encountered and fixed this problem before.
A similar thing I've seen (doesn't really relate to asio) is that Windows services don't get a console. Any writes to std::cout or std::cerr resulted in some sort of a crash (I don't recall the specifics). - Marsh
participants (4)
-
Evan Burkitt
-
Hajo Kirchhoff
-
Igor R
-
Marsh Ray