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:
commit
9c17d8e805
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user