Hi all,
again on the problem of pan not being able to resume downloads
in case the ADSL (or whatever) link to the server is lost. I've made a
fix in sockets.c (diff patch appended).
Changes are:
- the io_channel is made non-blocking, so that EAGAIN can actually be a
return value for read/write operations.
- after each EAGAIN, we sleep one second and increment a counter. When
the counter hits PAN_SOCK_FAILED_OP_THRESHOLD the connection is
dropped as in the case of an error. Pan will then reattempt to
connect as normal.
Caveats:
- it SEEMS to be working, this does not mean it's perfect or 100%
reliable, please test and report. I'm not certain of the way
the code handles EAGAIN in read mode.
- the value of PAN_SOCK_FAILED_OP_THRESHOLD has a default of 60. If you
are on a 56K modem and you use a ton of connections this may be too low.
Bye,
Alberto
--
diff -ur pan-0.14.0.original/pan/sockets.c pan-0.14.0/pan/sockets.c
--- pan-0.14.0.original/pan/sockets.c 2003-04-08 22:13:33.000000000
+0200
+++ pan-0.14.0/pan/sockets.c 2003-05-10 09:44:27.000000000 +0200
@@ -69,8 +69,13 @@
guint bytes_read;
guint bytes_written;
time_t byte_count_start_time;
+
+ gint failed_operations;
};
+
+#define PAN_SOCK_FAILED_OP_THRESHOLD 60
+
/*********************
********************** Variables
*********************/
@@ -126,6 +131,7 @@
sock->bytes_read = 0u;
sock->bytes_written = 0u;
sock->byte_count_start_time = time(NULL);
+ sock->failed_operations = 0;
sock->line_buffer = g_string_sized_new (512);
sock->error = FALSE;
sock->need_auth = FALSE;
@@ -142,6 +148,7 @@
sock->gio_channel = gnet_tcp_socket_get_iochannel
(sock->gnet_socket);
if (g_io_channel_get_encoding (sock->gio_channel) != NULL)
g_io_channel_set_encoding (sock->gio_channel, NULL, NULL);
+ g_io_channel_set_flags(sock->gio_channel, G_IO_FLAG_NONBLOCK,
NULL);
g_io_channel_set_buffered (sock->gio_channel, TRUE);
g_io_channel_set_line_term (sock->gio_channel, "\n", 1);
log_add_va (LOG_INFO, _("New connection %p for %s, port %d"),
sock, server_address, port);
@@ -221,6 +228,12 @@
case G_IO_STATUS_AGAIN:
if (err != NULL)
g_error_free (err);
+ sock->failed_operations++;
+
+ if (sock->failed_operations >
PAN_SOCK_FAILED_OP_THRESHOLD) {
+ pan_socket_set_error_flag (sock, TRUE);
+ return -1;
+ }
g_usleep (G_USEC_PER_SEC);
continue;
case G_IO_STATUS_ERROR:
@@ -232,6 +245,7 @@
pan_socket_set_error_flag (sock, TRUE);
return -1;
case G_IO_STATUS_NORMAL:
+ sock->failed_operations = 0;
done = TRUE;
break;
}
@@ -280,11 +294,21 @@
case G_IO_STATUS_AGAIN:
if (err != NULL)
g_error_free (err);
+ sock->failed_operations++;
+
+ if (sock->failed_operations >
PAN_SOCK_FAILED_OP_THRESHOLD) {
+ pan_socket_set_error_flag (sock, TRUE);
+ return -1;
+ }
g_usleep (G_USEC_PER_SEC);
- /* fall through */
+ nleft -= bytes_written;
+ line += bytes_written;
+ continue;
+
case G_IO_STATUS_NORMAL:
nleft -= bytes_written;
line += bytes_written;
+ sock->failed_operations = 0;
continue;
case G_IO_STATUS_EOF:
case G_IO_STATUS_ERROR: