[project @ 2004-01-26 14:16:23 by bursa]

Fix crashes related to content_destroy() by adding lock, implement no_error_pages.

svn path=/import/netsurf/; revision=508
This commit is contained in:
James Bursa 2004-01-26 14:16:23 +00:00
parent 92941a762d
commit 658084359d
5 changed files with 69 additions and 17 deletions

View File

@ -213,6 +213,7 @@ void cache_shrink(void)
LOG(("size %lu, removing %p '%s'", size, e->content, e->content->url));
/* TODO: move to disc cache */
size -= e->content->size;
e->content->cache = 0;
content_destroy(e->content);
unused_list->prev = e->prev;
e->prev->next = unused_list;

View File

@ -195,6 +195,8 @@ struct content * content_create(char *url)
user_sentinel->p1 = user_sentinel->p2 = 0;
user_sentinel->next = 0;
c->user_list = user_sentinel;
c->lock = 0;
c->destroy_pending = false;
return c;
}
@ -326,8 +328,16 @@ void content_reformat(struct content *c, unsigned long width, unsigned long heig
void content_destroy(struct content *c)
{
struct content_user *user, *next;
assert(c != 0);
assert(c);
LOG(("content %p %s", c, c->url));
assert(!c->fetch);
assert(!c->cache);
if (c->lock) {
c->destroy_pending = true;
return;
}
if (c->type < HANDLER_MAP_COUNT)
handler_map[c->type].destroy(c);
for (user = c->user_list; user != 0; user = next) {
@ -435,8 +445,10 @@ void content_remove_user(struct content *c,
* and destroy content structure if not in state READY or DONE */
if (c->user_list->next == 0) {
LOG(("no users for %p %s", c, c->url));
if (c->fetch != 0)
if (c->fetch != 0) {
fetch_abort(c->fetch);
c->fetch = 0;
}
if (c->status < CONTENT_STATUS_READY) {
if (c->cache)
cache_destroy(c);
@ -444,6 +456,8 @@ void content_remove_user(struct content *c,
} else {
if (c->cache)
cache_freeable(c);
else
content_destroy(c);
}
}
}
@ -457,11 +471,14 @@ void content_broadcast(struct content *c, content_msg msg, char *error)
{
struct content_user *user, *next;
LOG(("content %s, message %i", c->url, msg));
c->lock++;
for (user = c->user_list->next; user != 0; user = next) {
next = user->next; /* user may be destroyed during callback */
if (user->callback != 0)
user->callback(msg, c, user->p1, user->p2, error);
}
if (--(c->lock) == 0 && c->destroy_pending)
content_destroy(c);
}

View File

@ -139,6 +139,10 @@ struct content {
struct fetch *fetch; /**< Associated fetch, or 0. */
unsigned long fetch_size; /**< Amount of data fetched so far. */
unsigned long total_size; /**< Total data size, 0 if unknown. */
int lock; /**< Content in use, do not destroy. */
bool destroy_pending; /**< Destroy when lock returns to 0. */
bool no_error_pages; /**< Used by fetchcache(). */
};

View File

@ -44,13 +44,28 @@ static void fetchcache_error_page(struct content *c, const char *error);
*
* If an error occurs immediately, 0 may be returned. Later errors will be
* reported via the callback.
*
* \param url address to fetch
* \param referer url of referring page, or 0 if none
* \param callback function to call when anything interesting happens to
* the new content
* \param p1 user parameter for callback
* \param p2 user parameter for callback
* \param width available space
* \param height available space
* \param no_error_pages if an error occurs, send CONTENT_MSG_ERROR instead
* of generating an error page
* \param post_urlenc url encoded post data, or 0 if none
* \param post_multipart multipart post data, or 0 if none
* \param cookies send and accept cookies
* \return a new content, or 0 if an error occurred and no_error_pages is true
*/
struct content * fetchcache(const char *url0, char *referer,
struct content * fetchcache(const char *url, char *referer,
void (*callback)(content_msg msg, struct content *c, void *p1,
void *p2, const char *error),
void *p1, void *p2, unsigned long width, unsigned long height,
bool only_2xx
bool no_error_pages
#ifdef WITH_POST
, char *post_urlenc,
struct form_successful_control *post_multipart
@ -61,8 +76,8 @@ struct content * fetchcache(const char *url0, char *referer,
)
{
struct content *c;
char *url = xstrdup(url0);
char *hash = strchr(url, '#');
char *url1 = xstrdup(url);
char *hash = strchr(url1, '#');
const char *params[] = { 0 };
char error_message[500];
@ -70,21 +85,21 @@ struct content * fetchcache(const char *url0, char *referer,
if (hash != 0)
*hash = 0;
LOG(("url %s", url));
LOG(("url %s", url1));
#ifdef WITH_POST
if (!post_urlenc && !post_multipart)
#endif
{
c = cache_get(url);
c = cache_get(url1);
if (c != 0) {
free(url);
free(url1);
content_add_user(c, callback, p1, p2);
return c;
}
}
c = content_create(url);
c = content_create(url1);
content_add_user(c, callback, p1, p2);
#ifdef WITH_POST
@ -95,7 +110,8 @@ struct content * fetchcache(const char *url0, char *referer,
c->fetch_size = 0;
c->width = width;
c->height = height;
c->fetch = fetch_start(url, referer, fetchcache_callback, c, only_2xx
c->no_error_pages = no_error_pages;
c->fetch = fetch_start(url1, referer, fetchcache_callback, c, no_error_pages
#ifdef WITH_POST
,post_urlenc, post_multipart
#endif
@ -107,11 +123,16 @@ struct content * fetchcache(const char *url0, char *referer,
LOG(("warning: fetch_start failed"));
if (c->cache)
cache_destroy(c);
if (no_error_pages) {
content_destroy(c);
free(url1);
return 0;
}
snprintf(error_message, sizeof error_message,
messages_get("InvalidURL"), url);
messages_get("InvalidURL"), url1);
fetchcache_error_page(c, error_message);
}
free(url);
free(url1);
return c;
}
@ -130,6 +151,8 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size)
char **params;
unsigned int i;
c->lock++;
switch (msg) {
case FETCH_TYPE:
c->total_size = size;
@ -167,11 +190,15 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size)
case FETCH_ERROR:
LOG(("FETCH_ERROR, '%s'", data));
c->fetch = 0;
/* content_broadcast(c, CONTENT_MSG_ERROR, data); */
if (c->cache)
cache_destroy(c);
content_reset(c);
fetchcache_error_page(c, data);
if (c->no_error_pages) {
content_broadcast(c, CONTENT_MSG_ERROR, data);
content_destroy(c);
} else {
content_reset(c);
fetchcache_error_page(c, data);
}
break;
case FETCH_REDIRECT:
@ -202,6 +229,9 @@ void fetchcache_callback(fetch_msg msg, void *p, char *data, unsigned long size)
default:
assert(0);
}
if (--(c->lock) == 0 && c->destroy_pending)
content_destroy(c);
}

View File

@ -27,7 +27,7 @@ struct content * fetchcache(const char *url, char *referer,
void (*callback)(content_msg msg, struct content *c, void *p1,
void *p2, const char *error),
void *p1, void *p2, unsigned long width, unsigned long height,
bool only_2xx
bool no_error_pages
#ifdef WITH_POST
, char *post_urlenc,
struct form_successful_control *post_multipart