Fix race when stopping an HTML content mid-load

svn path=/trunk/netsurf/; revision=12611
This commit is contained in:
John Mark Bell 2011-07-19 20:23:59 +00:00
parent 5fd24d7557
commit 1cd92d6d50
3 changed files with 61 additions and 30 deletions

View File

@ -1112,10 +1112,8 @@ nserror content_abort(struct content *c)
{
LOG(("Aborting %p", c));
if (c->status == CONTENT_STATUS_READY) {
if (c->handler->stop != NULL)
c->handler->stop(c);
}
if (c->handler->stop != NULL)
c->handler->stop(c);
/* And for now, abort our llcache object */
return llcache_handle_abort(c->llcache);

View File

@ -240,6 +240,7 @@ nserror html_create_html_data(html_content *c, const http_parameter *params)
c->encoding = NULL;
c->base_url = (char *) content__get_url(&c->base);
c->base_target = NULL;
c->aborted = false;
c->layout = NULL;
c->background_colour = NS_TRANSPARENT;
c->stylesheet_count = 0;
@ -482,11 +483,11 @@ bool html_convert(struct content *c)
return false;
}
htmlc->document =binding_get_document(htmlc->parser_binding,
htmlc->document = binding_get_document(htmlc->parser_binding,
&htmlc->quirks);
/*xmlDebugDumpDocument(stderr, htmlc->document);*/
if (!htmlc->document) {
if (htmlc->document == NULL) {
LOG(("Parsing failed"));
msg_data.error = messages_get("ParsingFail");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
@ -506,32 +507,39 @@ bool html_convert(struct content *c)
}
}
/* Give up processing if we've been aborted */
if (htmlc->aborted) {
msg_data.error = messages_get("Stopped");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/* locate html and head elements */
html = xmlDocGetRootElement(htmlc->document);
if (html == 0 || strcmp((const char *) html->name, "html") != 0) {
if (html == NULL || strcmp((const char *) html->name, "html") != 0) {
LOG(("html element not found"));
msg_data.error = messages_get("ParsingFail");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
for (head = html->children;
head != 0 && head->type != XML_ELEMENT_NODE;
head != NULL && head->type != XML_ELEMENT_NODE;
head = head->next)
;
if (head && strcmp((const char *) head->name, "head") != 0) {
head = 0;
head = NULL;
LOG(("head element not found"));
}
if (head) {
if (!html_head(htmlc, head)) {
if (head != NULL) {
if (html_head(htmlc, head) == false) {
msg_data.error = messages_get("NoMemory");
content_broadcast(c, CONTENT_MSG_ERROR, msg_data);
return false;
}
/* handle meta refresh */
if (!html_meta_refresh(htmlc, head))
if (html_meta_refresh(htmlc, head) == false)
return false;
}
@ -572,7 +580,7 @@ bool html_convert(struct content *c)
}
/* get stylesheets */
if (!html_find_stylesheets(htmlc, html))
if (html_find_stylesheets(htmlc, html) == false)
return false;
return true;
@ -590,6 +598,14 @@ void html_finish_conversion(html_content *c)
uint32_t i;
css_error error;
/* Bail out if we've been aborted */
if (c->aborted) {
msg_data.error = messages_get("Stopped");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
c->base.status = CONTENT_STATUS_ERROR;
return;
}
html = xmlDocGetRootElement(c->document);
assert(html != NULL);
@ -606,7 +622,7 @@ void html_finish_conversion(html_content *c)
if (error != CSS_OK) {
msg_data.error = messages_get("NoMemory");
content_broadcast(&c->base, CONTENT_MSG_ERROR, msg_data);
c->base.status = CONTENT_MSG_ERROR;
c->base.status = CONTENT_STATUS_ERROR;
return;
}
@ -1703,7 +1719,7 @@ void html_object_refresh(void *p)
}
/**
* Stop loading a CONTENT_HTML in state READY.
* Stop loading a CONTENT_HTML.
*/
void html_stop(struct content *c)
@ -1711,24 +1727,38 @@ void html_stop(struct content *c)
html_content *htmlc = (html_content *) c;
struct content_html_object *object;
assert(c->status == CONTENT_STATUS_READY);
switch (c->status) {
case CONTENT_STATUS_LOADING:
/* Still loading; simply flag that we've been aborted
* html_convert/html_finish_conversion will do the rest */
htmlc->aborted = true;
break;
case CONTENT_STATUS_READY:
for (object = htmlc->object_list; object != NULL;
object = object->next) {
if (object->content == NULL)
continue;
for (object = htmlc->object_list; object != NULL;
object = object->next) {
if (object->content == NULL)
continue;
if (content_get_status(object->content) == CONTENT_STATUS_DONE)
; /* already loaded: do nothing */
else if (content_get_status(object->content) ==
CONTENT_STATUS_READY)
hlcache_handle_abort(object->content);
else {
hlcache_handle_release(object->content);
object->content = NULL;
if (content_get_status(object->content) ==
CONTENT_STATUS_DONE)
; /* already loaded: do nothing */
else if (content_get_status(object->content) ==
CONTENT_STATUS_READY)
hlcache_handle_abort(object->content);
else {
hlcache_handle_release(object->content);
object->content = NULL;
}
}
c->status = CONTENT_STATUS_DONE;
break;
case CONTENT_STATUS_DONE:
/* Nothing to do */
break;
default:
LOG(("Unexpected status %d", c->status));
assert(0);
}
c->status = CONTENT_STATUS_DONE;
}

View File

@ -48,6 +48,9 @@ typedef struct html_content {
/** Base target */
char *base_target;
/** Content has been aborted in the LOADING state */
bool aborted;
/** Box tree, or NULL. */
struct box *layout;
/** Document background colour. */