1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-12-04 14:46:47 -05:00

Merge branch 'elinks-0.12' into elinks-0.13

This commit is contained in:
Kalle Olavi Niemitalo 2008-10-04 15:13:33 +03:00 committed by Kalle Olavi Niemitalo
commit 9c17d8e805
2 changed files with 45 additions and 5 deletions

View File

@ -118,13 +118,19 @@ get_connections_transfering_count(void)
return i;
}
/** Check whether the pointer @a conn still points to a connection
* with the given @a id. If the struct connection has already been
* freed, this returns 0. By comparing connection.id, this function
* can usually detect even the case where a different connection has
* been created at the same address. For that to work, the caller
* must save the connection.id before the connection can be deleted. */
static inline int
connection_disappeared(struct connection *conn)
connection_disappeared(struct connection *conn, unsigned int id)
{
struct connection *c;
foreach (c, connection_queue)
if (conn == c && conn->id == c->id)
if (conn == c && id == c->id)
return 0;
return 1;
@ -361,17 +367,19 @@ set_connection_state(struct connection *conn, struct connection_state state)
conn->state = state;
if (is_in_state(conn->state, S_TRANS)) {
const unsigned int id = conn->id;
if (upload_progress && upload_progress->timer == TIMER_ID_UNDEF) {
start_update_progress(upload_progress,
(void (*)(void *)) upload_stat_timer, conn);
upload_stat_timer(conn);
if (connection_disappeared(conn))
if (connection_disappeared(conn, id))
return;
}
if (progress->timer == TIMER_ID_UNDEF) {
start_update_progress(progress, (void (*)(void *)) stat_timer, conn);
update_connection_progress(conn);
if (connection_disappeared(conn))
if (connection_disappeared(conn, id))
return;
}
@ -450,13 +458,15 @@ static void
notify_connection_callbacks(struct connection *conn)
{
struct connection_state state = conn->state;
unsigned int id = conn->id;
struct download *download, *next;
foreachsafe (download, next, conn->downloads) {
download->cached = conn->cached;
if (download->callback)
download->callback(download, download->data);
if (is_in_progress_state(state) && connection_disappeared(conn))
if (is_in_progress_state(state)
&& connection_disappeared(conn, id))
return;
}
}

View File

@ -69,6 +69,16 @@ struct connect_info {
struct uri *uri; /* For updating the blacklist. */
};
/** For detecting whether a struct socket has been deleted while a
* function was using it. */
struct socket_weak_ref {
LIST_HEAD(struct socket_weak_ref);
/** done_socket() resets this to NULL. */
struct socket *socket;
};
static INIT_LIST_OF(struct socket_weak_ref, socket_weak_refs);
/* To enable logging of tranfers, for debugging purposes. */
#if 0
@ -143,6 +153,8 @@ init_socket(void *conn, struct socket_operations *ops)
void
done_socket(struct socket *socket)
{
struct socket_weak_ref *ref;
close_socket(socket);
if (socket->connect_info)
@ -150,6 +162,11 @@ done_socket(struct socket *socket)
mem_free_set(&socket->read_buffer, NULL);
mem_free_set(&socket->write_buffer, NULL);
foreach(ref, socket_weak_refs) {
if (ref->socket == socket)
ref->socket = NULL;
}
}
void
@ -935,13 +952,26 @@ void
read_from_socket(struct socket *socket, struct read_buffer *buffer,
struct connection_state state, socket_read_T done)
{
const int is_buffer_new = (buffer != socket->read_buffer);
struct socket_weak_ref ref;
select_handler_T write_handler;
ref.socket = socket;
add_to_list(socket_weak_refs, &ref);
buffer->done = done;
socket->ops->set_timeout(socket, connection_state(0));
socket->ops->set_state(socket, state);
del_from_list(&ref);
if (ref.socket == NULL) {
/* socket->ops->set_state deleted the socket. */
if (is_buffer_new)
mem_free(buffer);
return;
}
if (socket->read_buffer && buffer != socket->read_buffer)
mem_free(socket->read_buffer);
socket->read_buffer = buffer;