summaryrefslogtreecommitdiff
path: root/content
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2004-01-26 14:16:23 +0000
committerJames Bursa <james@netsurf-browser.org>2004-01-26 14:16:23 +0000
commit658084359d02596b425a27ac4c452ff65f73e1f8 (patch)
tree2cde49b9de968585587aa742f77487acaebdf7df /content
parent92941a762d0abe39136ad73562fa130fbd39db57 (diff)
downloadnetsurf-658084359d02596b425a27ac4c452ff65f73e1f8.tar.gz
netsurf-658084359d02596b425a27ac4c452ff65f73e1f8.tar.bz2
[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
Diffstat (limited to 'content')
-rw-r--r--content/cache.c1
-rw-r--r--content/content.c21
-rw-r--r--content/content.h4
-rw-r--r--content/fetchcache.c58
-rw-r--r--content/fetchcache.h2
5 files changed, 69 insertions, 17 deletions
diff --git a/content/cache.c b/content/cache.c
index 5e95f4c6e..760f54679 100644
--- a/content/cache.c
+++ b/content/cache.c
@@ -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;
diff --git a/content/content.c b/content/content.c
index 596672b9d..4b4e19bff 100644
--- a/content/content.c
+++ b/content/content.c
@@ -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);
}
diff --git a/content/content.h b/content/content.h
index 7235011a4..737942187 100644
--- a/content/content.h
+++ b/content/content.h
@@ -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(). */
};
diff --git a/content/fetchcache.c b/content/fetchcache.c
index e7e8f2b3a..f2ad43a71 100644
--- a/content/fetchcache.c
+++ b/content/fetchcache.c
@@ -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);
}
diff --git a/content/fetchcache.h b/content/fetchcache.h
index cbd447aa1..37d3e1f18 100644
--- a/content/fetchcache.h
+++ b/content/fetchcache.h
@@ -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