attempt to fix crash bug when cancelling a download

This commit is contained in:
David White 2009-02-22 01:27:50 +00:00
parent 46cd652c7f
commit bc0273c41a
4 changed files with 57 additions and 19 deletions

View File

@ -237,6 +237,7 @@ pending_statistics get_pending_stats()
manager::manager(size_t min_threads, size_t max_threads) : free_(true)
{
fprintf(stderr, "NETWORK MANAGER CALLED!\n");
// If the network is already being managed
if(socket_set) {
free_ = false;
@ -588,20 +589,12 @@ connection accept_connection()
return 0;
}
bool disconnect(connection s, bool force)
bool disconnect(connection s)
{
if(s == 0) {
while(sockets.empty() == false) {
assert(sockets.back() != 0);
size_t n = 0;
while(disconnect(sockets.back()) == false) {
// force a disconnect
if (n > 100) {
disconnect(sockets.back(), true);
n = 0;
continue;
}
++n;
SDL_Delay(1);
}
}
@ -615,7 +608,7 @@ bool disconnect(connection s, bool force)
{
return true;
}
if (!network_worker_pool::close_socket(info->second.sock, force)) {
if (!network_worker_pool::close_socket(info->second.sock)) {
return false;
}
}

View File

@ -130,7 +130,7 @@ connection accept_connection();
* in the middle of sending/receiving data.
* The socket will be closed when it has finished its send/receive.
*/
bool disconnect(connection connection_num=0, bool force=false);
bool disconnect(connection connection_num=0);
/**
* Function to queue a disconnection.

View File

@ -237,9 +237,33 @@ bool receive_with_timeout(TCPsocket s, char* buf, size_t nbytes,
#ifdef USE_POLL
struct pollfd fd = { ((_TCPsocket*)s)->channel, POLLIN, 0 };
int poll_res;
//we timeout of the poll every 100ms. This lets us check to
//see if we have been disconnected, in which case we should
//abort the receive.
const int poll_timeout = std::min(timeout_ms, 100);
do {
poll_res = poll(&fd, 1, timeout_ms);
} while(poll_res == -1 && errno == EINTR);
poll_res = poll(&fd, 1, poll_timeout);
if(poll_res == 0) {
timeout_ms -= poll_timeout;
if(timeout_ms <= 0) {
//we've been waiting too long; abort the receive
//as having failed due to timeout.
return false;
}
//check to see if we've been interrupted
const size_t shard = get_shard(s);
const threading::lock lock(*shard_mutexes[shard]);
socket_state_map::iterator lock_it = sockets_locked[shard].find(s);
assert(lock_it != sockets_locked[shard].end());
if(lock_it->second == SOCKET_INTERRUPT) {
return false;
}
}
} while(poll_res == 0 || poll_res == -1 && errno == EINTR);
if (poll_res < 1)
return false;
@ -250,11 +274,31 @@ bool receive_with_timeout(TCPsocket s, char* buf, size_t nbytes,
int retval;
struct timeval tv;
tv.tv_sec = timeout_ms/1000;
tv.tv_usec = timeout_ms % 1000;
const int select_timeout = std::min(timeout_ms, 100);
tv.tv_sec = select_timeout/1000;
tv.tv_usec = select_timeout % 1000;
do {
retval = select(((_TCPsocket*)s)->channel + 1, &readfds, NULL, NULL, &tv);
} while(retval == -1 && errno == EINTR);
if(retval == 0) {
timeout_ms -= select_timeout;
if(timeout_ms <= 0) {
//we've been waiting too long; abort the receive
//as having failed due to timeout.
return false;
}
//check to see if we've been interrupted
const size_t shard = get_shard(s);
const threading::lock lock(*shard_mutexes[shard]);
socket_state_map::iterator lock_it = sockets_locked[shard].find(s);
assert(lock_it != sockets_locked[shard].end());
if(lock_it->second == SOCKET_INTERRUPT) {
return false;
}
}
} while(retval == 0 || retval == -1 && errno == EINTR);
if (retval < 1)
return false;
@ -288,6 +332,7 @@ bool receive_with_timeout(TCPsocket s, char* buf, size_t nbytes,
}
{
const size_t shard = get_shard(s);
const threading::lock lock(*shard_mutexes[shard]);
socket_state_map::iterator lock_it = sockets_locked[shard].find(s);
assert(lock_it != sockets_locked[shard].end());
if(lock_it->second == SOCKET_INTERRUPT) {
@ -1020,7 +1065,7 @@ bool is_locked(const TCPsocket sock) {
return (lock_it->second == SOCKET_LOCKED);
}
bool close_socket(TCPsocket sock, bool force)
bool close_socket(TCPsocket sock)
{
{
const size_t shard = get_shard(sock);
@ -1037,7 +1082,7 @@ bool close_socket(TCPsocket sock, bool force)
remove_buffers(sock);
return true;
}
if (!(lock_it->second == SOCKET_LOCKED || lock_it->second == SOCKET_INTERRUPT) || force) {
if (!(lock_it->second == SOCKET_LOCKED || lock_it->second == SOCKET_INTERRUPT)) {
sockets_locked[shard].erase(lock_it);
remove_buffers(sock);
return true;

View File

@ -62,7 +62,7 @@ void queue_file(TCPsocket sock, const std::string&);
void queue_raw_data(TCPsocket sock, const char* buf, int len);
size_t queue_data(TCPsocket sock, const config& buf, const bool gzipped, const std::string& packet_type);
bool is_locked(const TCPsocket sock);
bool close_socket(TCPsocket sock, bool force=false);
bool close_socket(TCPsocket sock);
TCPsocket detect_error();
std::pair<network::statistics,network::statistics> get_current_transfer_stats(TCPsocket sock);