Opened 12 years ago

Closed 12 years ago

Last modified 9 years ago

#5311 closed Bugs (invalid)

io_service::post/dispatch, io_service::stop, deadline_timer crashes

Reported by: nfries88@… Owned by: chris_kohlhoff
Milestone: To Be Determined Component: asio
Version: Boost 1.46.0 Severity: Problem
Keywords: asio, io_service, post, dispatch, stop, deadline_timer, crash Cc:

Description

I've used programs using boost::asio before, but never used it directly myself. I made a test program using boost::asio that models communications from a synchronous TCP server to an asynchronous TCP client.

<Long version> The program launches one thread for the server, which creates an acceptor and calls async_accept; then runs the io_service. Upon accepting a new connection with success, it immediately begins an async read on the new connection and another async_accept. On the original thread, I create a TCP socket (using a separate io_service), connect it to the server, and send a packet saying "Hello, Server". When the server thread receives this "Hello, Server" packet, it responds with a "Hello, Client" packet and begins another async_read with a newly-allocated buffer. When the client receives this "Hello, Client" packet, since the test program has nothing else to do, I begin cleaning up by calling io_service::stop on the server's io_service. That crashed. I guessed that maybe it was my fault, so instead I called service.post(bind(&io_service::stop, &service));. This crashed, so I tried the same with service.dispatch(). Now I was confused, so I tried a third time with a deadline_timer that expired after 1 millisecond. This also crashes.

<Short version> io_service::post, io_service::dispatch, and io_service::stop are all crashing when called from a thread other than the one running the io_service. An async_read and async_accept are in progress, but no reading or connecting is being done. deadline_timer::async_wait() crashes when called from a thread other than the one calling io_service::run

Also, none of these crashes are caught by try{}catch(){}.

<Compiler and System Information> Compiler: TDM-MinGW GCC 4.4.1 32-bit Compiler Flags: -Wall -s -O2 Boost Version: 1.46.0 System: Windows 7 Home Premium 64-bit CPU: AMD Turion II P540 (dual-core, 2.40ghz)

<Information from the crash pop-up> Problem signature:

Problem Event Name: APPCRASH Application Name: nettest.exe Application Version: 0.0.0.0 Application Timestamp: 4d7fc897 Fault Module Name: nettest.exe Fault Module Version: 0.0.0.0 Fault Module Timestamp: 4d7fc897 Exception Code: c0000005 Exception Offset: 0002c702 OS Version: 6.1.7600.2.0.0.768.3 Locale ID: 1033 Additional Information 1: 0a9e Additional Information 2: 0a9e372d3b4ad19135b953a78882e789 Additional Information 3: 0a9e Additional Information 4: 0a9e372d3b4ad19135b953a78882e789

Attachments (1)

net.zip (7.5 KB ) - added by nfries88@… 12 years ago.
full test program source code

Download all attachments as: .zip

Change History (6)

comment:1 by chris_kohlhoff, 12 years ago

Please supply some minimal sample code exhibiting the problem. Unfortunately, your description is insufficient to be able say where the problem lies.

by nfries88@…, 12 years ago

Attachment: net.zip added

full test program source code

comment:2 by nfries88@…, 12 years ago

I attached the full source code for the test program, define NETTEST to have the server send the response.

comment:3 by chris_kohlhoff, 12 years ago

Resolution: invalid
Status: newclosed

If you use a debugger you will probably see that the myservice pointer is always null. Specifically, your Service class's constructor calls doWork() which in turn calls io_service.run(). This means the constructor never returns, and the myservice global is never set in runServer().

N.B. Even if you move the doWork() call out of the constructor, you will still have a race condition in the initialisation of the myservice global.

Unrelated: if you stop your service in this way you will also leak the Connection object that is created in Service::accept().

in reply to:  3 comment:4 by anonymous, 12 years ago

Replying to chris_kohlhoff:

N.B. Even if you move the doWork() call out of the constructor, you will still have a race condition in the initialisation of the myservice global.

why is that? I'm not having any issues.

And sorry to waste your time with an invalid bug. But thanks to your input and a little more reading of the documentation, it seems to be stable now.

comment:5 by kyaw.tech@…, 9 years ago

Subject : C++ Dealing with Concurrency using Boost.Asio (Visual Studio 2008 SP1)

Dear Chris,

I am looking for the concrete advice or solution for the C++ Dealing with Concurrency using Boost.Asio.

Since my APIs need to communicate between multiple(lots of) clients (workstations) and servers.

There are four ways of handling concurrency in the document named using Asio with C++ 11.

1) Single Thread

2) Use Threads for long running tasks

3) Multiple io_sevices, one thread each

4) one io_service, multiple threads

I am very concern about the throughput and latency for network traffic because of heavy data transactions.

I hope some one will help me to close the case asap since I need to proceed further.

Thanks and best regards

Note: See TracTickets for help on using tickets.