libfetch: fix races in the cache connection code.
Tested by @Gottox.
This commit is contained in:
parent
6a985190aa
commit
4ee6f943dd
4
NEWS
4
NEWS
@ -1,8 +1,6 @@
|
|||||||
xbps-0.43 (???):
|
xbps-0.43 (???):
|
||||||
|
|
||||||
* libxbps: xbps_archive_fetch_xxx() are now protected with a mutex to avoid
|
* libfetch: fix races in the cache connection code.
|
||||||
data races with 8 threads or more. Reproducable by @chneukirchen on a
|
|
||||||
8 core machine.
|
|
||||||
|
|
||||||
xbps-0.42 (2014-12-22):
|
xbps-0.42 (2014-12-22):
|
||||||
|
|
||||||
|
@ -66,6 +66,8 @@
|
|||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
#include "fetch.h"
|
#include "fetch.h"
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
|
|
||||||
@ -333,6 +335,7 @@ fetch_connect(struct url *url, int af, int verbose)
|
|||||||
return (conn);
|
return (conn);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static pthread_mutex_t cache_mtx = PTHREAD_MUTEX_INITIALIZER;
|
||||||
static conn_t *connection_cache;
|
static conn_t *connection_cache;
|
||||||
static int cache_global_limit = 0;
|
static int cache_global_limit = 0;
|
||||||
static int cache_per_host_limit = 0;
|
static int cache_per_host_limit = 0;
|
||||||
@ -379,6 +382,7 @@ fetch_cache_get(const struct url *url, int af)
|
|||||||
{
|
{
|
||||||
conn_t *conn, *last_conn = NULL;
|
conn_t *conn, *last_conn = NULL;
|
||||||
|
|
||||||
|
pthread_mutex_lock(&cache_mtx);
|
||||||
for (conn = connection_cache; conn; conn = conn->next_cached) {
|
for (conn = connection_cache; conn; conn = conn->next_cached) {
|
||||||
if (conn->cache_url->port == url->port &&
|
if (conn->cache_url->port == url->port &&
|
||||||
strcmp(conn->cache_url->scheme, url->scheme) == 0 &&
|
strcmp(conn->cache_url->scheme, url->scheme) == 0 &&
|
||||||
@ -391,9 +395,12 @@ fetch_cache_get(const struct url *url, int af)
|
|||||||
last_conn->next_cached = conn->next_cached;
|
last_conn->next_cached = conn->next_cached;
|
||||||
else
|
else
|
||||||
connection_cache = conn->next_cached;
|
connection_cache = conn->next_cached;
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&cache_mtx);
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pthread_mutex_unlock(&cache_mtx);
|
||||||
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -414,6 +421,7 @@ fetch_cache_put(conn_t *conn, int (*closecb)(conn_t *))
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pthread_mutex_lock(&cache_mtx);
|
||||||
global_count = host_count = 0;
|
global_count = host_count = 0;
|
||||||
last = NULL;
|
last = NULL;
|
||||||
for (iter = connection_cache; iter;
|
for (iter = connection_cache; iter;
|
||||||
@ -435,6 +443,7 @@ fetch_cache_put(conn_t *conn, int (*closecb)(conn_t *))
|
|||||||
conn->cache_close = closecb;
|
conn->cache_close = closecb;
|
||||||
conn->next_cached = connection_cache;
|
conn->next_cached = connection_cache;
|
||||||
connection_cache = conn;
|
connection_cache = conn;
|
||||||
|
pthread_mutex_unlock(&cache_mtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <pthread.h>
|
|
||||||
|
|
||||||
#include "xbps_api_impl.h"
|
#include "xbps_api_impl.h"
|
||||||
|
|
||||||
@ -44,7 +43,6 @@ struct fetch_archive {
|
|||||||
struct url *url;
|
struct url *url;
|
||||||
struct fetchIO *fetch;
|
struct fetchIO *fetch;
|
||||||
char buffer[32768];
|
char buffer[32768];
|
||||||
pthread_mutex_t mtx;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -52,9 +50,7 @@ fetch_archive_open(struct archive *a _unused, void *client_data)
|
|||||||
{
|
{
|
||||||
struct fetch_archive *f = client_data;
|
struct fetch_archive *f = client_data;
|
||||||
|
|
||||||
pthread_mutex_lock(&f->mtx);
|
|
||||||
f->fetch = fetchGet(f->url, NULL);
|
f->fetch = fetchGet(f->url, NULL);
|
||||||
pthread_mutex_unlock(&f->mtx);
|
|
||||||
|
|
||||||
if (f->fetch == NULL)
|
if (f->fetch == NULL)
|
||||||
return ENOENT;
|
return ENOENT;
|
||||||
@ -66,13 +62,9 @@ static ssize_t
|
|||||||
fetch_archive_read(struct archive *a _unused, void *client_data, const void **buf)
|
fetch_archive_read(struct archive *a _unused, void *client_data, const void **buf)
|
||||||
{
|
{
|
||||||
struct fetch_archive *f = client_data;
|
struct fetch_archive *f = client_data;
|
||||||
ssize_t res;
|
|
||||||
|
|
||||||
*buf = f->buffer;
|
*buf = f->buffer;
|
||||||
pthread_mutex_lock(&f->mtx);
|
return fetchIO_read(f->fetch, f->buffer, sizeof(f->buffer));
|
||||||
res = fetchIO_read(f->fetch, f->buffer, sizeof(f->buffer));
|
|
||||||
pthread_mutex_unlock(&f->mtx);
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
@ -80,11 +72,8 @@ fetch_archive_close(struct archive *a _unused, void *client_data)
|
|||||||
{
|
{
|
||||||
struct fetch_archive *f = client_data;
|
struct fetch_archive *f = client_data;
|
||||||
|
|
||||||
pthread_mutex_lock(&f->mtx);
|
|
||||||
if (f->fetch != NULL)
|
if (f->fetch != NULL)
|
||||||
fetchIO_close(f->fetch);
|
fetchIO_close(f->fetch);
|
||||||
pthread_mutex_unlock(&f->mtx);
|
|
||||||
pthread_mutex_destroy(&f->mtx);
|
|
||||||
free(f);
|
free(f);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@ -101,7 +90,6 @@ open_archive_by_url(struct url *url)
|
|||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
f->url = url;
|
f->url = url;
|
||||||
pthread_mutex_init(&f->mtx, NULL);
|
|
||||||
|
|
||||||
if ((a = archive_read_new()) == NULL) {
|
if ((a = archive_read_new()) == NULL) {
|
||||||
free(f);
|
free(f);
|
||||||
|
Loading…
Reference in New Issue
Block a user