hi, sorry for the vague question, but i'm not entirely sure what the problem here is... i have a class hierarchy (has-a relationship) like this: fcgi_server_connection +-fcgi_application +-fcgi_cgi fcgi_server_connection has a tcp::socket 'server_socket'. fcgi_cgi has another tcp::socket, 'child_socket'. the program asynchronously reads messages from server_socket then writes them to child_socket, and reads messages from child_socket then writes them to server_socket. (there is some intermediate processing, but i don't think it affects the problem.) the problem occurs when deleting these connections. firstly, fcgi_server_connection is deleted. this deletes fcgi_application, which deletes fcgi_cgi. the sockets are member objects, so they are deleted as part of this. the actual problem is this: sometimes, after a socket is deleted, instead of oustanding read/write operations returning with asio::error::operation_aborted, they return with no error (error==0), but with socket.native() equal to -1. my understanding is that once the socket is deleted, all outstanding operations should be cancelled and operation_aborted should be returned. is this right? if so, what might cause the behaviour i'm seeing? and if not, what am i missing? thanks, - river.
the actual problem is this: sometimes, after a socket is deleted, instead of oustanding read/write operations returning with asio::error::operation_aborted, they return with no error (error==0), but with socket.native() equal to -1.
Those operations probably had completed *just before* you closed the socket...
Igor R:
the actual problem is this: sometimes, after a socket is deleted, instead of oustanding read/write operations returning with asio::error::operation_aborted, they return with no error (error==0), but with socket.native() equal to -1.
Those operations probably had completed *just before* you closed the socket...
so, if i understand correctly, there are pending calls for these events on the io_service queue, and when the socket is deleted, these calls are not removed? if so, how do i fix this? or more generally: how can i safely release an object holding a socket while there may be outstanding i/o operations? i've looked through the asio documentation, but i don't see anything about this in the tutorial or the example programs. i had assumed that socket::cancel() was the right solution to this, but it seems this is not the case... - river.
so, if i understand correctly, there are pending calls for these events on the io_service queue, and when the socket is deleted, these calls are not removed?
I meant there might be pending *callbacks* - of the operations that had already completed. The asio guarantees that every outstanding async. call will complete with calling your handler, so the handlers cannot be just thrown-away. So if the operation was aborted, your handler is called with some error_code, but if it succeeded - you'll get error_code == 0.
if so, how do i fix this? or more generally: how can i safely release an object holding a socket while there may be outstanding i/o operations?
You can just close() the socket - this will abort all the oustanding operations. (When calling close() keep in mind that asio socket instance is not threadsafe.) I believe, the simplest and the safest way to *release* the things is to let your object (with its socket) to "die" automatically: just bind you object's shared_ptr to the handler you pass to ASIO, and after the last handler is called, your object (and the socket) will be deleted. This is exactly the pattern used in all the exapmples.
i had assumed that socket::cancel() was the right solution to this, but it seems this is not the case...
cancel() won't work on some Windows versions, so in your case it's better to use close().
participants (2)
-
Igor R
-
River Tarnell