mirror of
https://github.com/rkd77/elinks.git
synced 2024-12-04 14:46:47 -05:00
Bug 951: Lock the cache entry while the hook runs.
This commit is contained in:
parent
314a41588c
commit
06c39a8ac4
@ -45,6 +45,8 @@ elinks.load_uri(uri, callback)
|
||||
|
||||
displays a fortune.
|
||||
|
||||
The cache object will not expire until after the callback returns.
|
||||
|
||||
|
||||
Properties
|
||||
----------
|
||||
@ -183,6 +185,8 @@ elinks.preformat_html(cached, vs)
|
||||
to elinks.preformat_html_hooks rather than to assign it to
|
||||
elinks.preformat_html.
|
||||
|
||||
The cache object will not expire until after this function returns.
|
||||
|
||||
|
||||
elinks.goto_url_hook(url)
|
||||
|
||||
@ -210,7 +214,14 @@ cache
|
||||
|
||||
The cache object mentioned in the descriptions of elinks.load_uri and
|
||||
elinks.preformat_html is a wrapper for the internal ELinks cache object.
|
||||
Its properties are:
|
||||
ELinks passes the ECMAScript cache object as an argument to your
|
||||
ECMAScript function, and keeps the corresponding document in the
|
||||
cache until the function returns. After that, ELinks may remove the
|
||||
document from the cache, even if the function has saved the cache
|
||||
object to some global variable. Such an expired cache object does
|
||||
not work but it does not crash ELinks either.
|
||||
|
||||
The properties of the cache object are:
|
||||
|
||||
cached.content (string)
|
||||
|
||||
|
@ -249,6 +249,9 @@ Description:
|
||||
add_fragment(cached, 0, new_string, new_len);
|
||||
normalize_cache_entry(cached, new_len);
|
||||
|
||||
The caller must ensure that there is a reference to cached, so that
|
||||
calling garbage_collection() from the event handler cannot free it.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Name: quit
|
||||
Managed By: The scripting subsystem/backends
|
||||
|
@ -220,6 +220,12 @@ static const JSClass cache_entry_class = {
|
||||
JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, cache_entry_finalize
|
||||
};
|
||||
|
||||
/** Return an SMJS object through which scripts can access @a cached.
|
||||
* If there already is such an object, return that; otherwise create a
|
||||
* new one. The SMJS object holds only a weak reference to @a cached;
|
||||
* so if the caller wants to guarantee that @a cached exists at least
|
||||
* until a script returns, it should use lock_object() and
|
||||
* unlock_object(). */
|
||||
JSObject *
|
||||
smjs_get_cache_entry_object(struct cache_entry *cached)
|
||||
{
|
||||
|
@ -32,6 +32,13 @@ smjs_loading_callback(struct download *download, void *data)
|
||||
|
||||
if (!download->cached) goto end;
|
||||
|
||||
/* download->cached->object.refcount is typically 0 here
|
||||
* because no struct document uses the cache entry. Because
|
||||
* the connection is no longer using the cache entry either,
|
||||
* it can be garbage collected. Don't let that happen while
|
||||
* the script is using it. */
|
||||
object_lock(download->cached);
|
||||
|
||||
assert(hop->callback);
|
||||
|
||||
smjs_ses = hop->ses;
|
||||
@ -44,6 +51,8 @@ smjs_loading_callback(struct download *download, void *data)
|
||||
JS_CallFunction(smjs_ctx, NULL, hop->callback, 1, args, &rval);
|
||||
|
||||
end:
|
||||
if (download->cached)
|
||||
object_unlock(download->cached);
|
||||
mem_free(download->data);
|
||||
mem_free(download);
|
||||
|
||||
|
@ -513,6 +513,17 @@ maybe_pre_format_html(struct cache_entry *cached, struct session *ses)
|
||||
if (!cached || cached->preformatted)
|
||||
return;
|
||||
|
||||
/* The script called from here may indirectly call
|
||||
* garbage_collection(). If the refcount of the cache entry
|
||||
* were 0, it could then be freed, and the
|
||||
* cached->preformatted assignment at the end of this function
|
||||
* would crash. Normally, the document has a reference to the
|
||||
* cache entry, and that suffices. If the following assertion
|
||||
* ever fails, object_lock(cached) and object_unlock(cached)
|
||||
* must be added to this function. */
|
||||
assert(cached->object.refcount > 0);
|
||||
if_assert_failed return;
|
||||
|
||||
fragment = get_cache_fragment(cached);
|
||||
if (!fragment) return;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user