[whatwg] RFC: Alternatives to storage mutex for cookies and localStorage

Aaron Boodman aa at google.com
Tue Sep 8 15:14:25 PDT 2009


On Tue, Sep 8, 2009 at 12:02 PM, Jonas Sicking<jonas at sicking.cc> wrote:
> On Tue, Sep 8, 2009 at 11:53 AM, Aaron Boodman<aa at google.com> wrote:
>> On Tue, Sep 8, 2009 at 11:23 AM, Chris Jones<cjones at mozilla.com> wrote:
>>> In general, I agree with Rob about this proposal.  What problem with storage
>>> mutex as spec'd today does your proposal solve?
>>
>> The spec requires a single storage mutex for the entire UA. Therefore
>> in a MELUA a web page can become unresponsive while waiting for some
>> other page to give up the lock. This is not good and something we have
>> tried to avoid everywhere else in the spec.
>>
>> Attempts to address this by doing per-origin locks wind up with
>> deadlocks being possible.
>
> How could this happen. It certainly does sound scary to have a bunch
> of locks that can be grabbed in arbitrary order, but I can't off the
> top of my head think of any ways where deadlocks can happen.

>From a Hixie mail way back in March:
http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2009-March/018991.html

<snip>
If it can be shown that it is not ever possible for script in one origin
to synchronously invoke script in another origin, then I guess we could
have per-origin locks instead of a single lock.
</snip>

Here are two cases I know of where it is possible to have synchronous
script execution across origins:

* Plugins. It is possible for script to invoke a plugin function in
one frame, and for the plugin to synchronously execute script in
another frame. We have addressed this in the spec by saying that
invoking a plugin releases the storage mutex, but that doesn't really
solve the problem. We are exchanging violation of run-to-completion
for deadlock. I guess it is an improvement, but it is still a bug.

* In WebKit, onresize is invoked synchronously. You can cause
cross-origin synchronous script execution by resizing an iframe.
AFAIK, the spec does not disallow this event from being synchronous.

I found the second case after only a few minutes of thinking about it.
I suspect there are more since it was never a design goal to prevent
synchronous script execution across origins.

We could patch each case like this by releasing the mutex, but each
time we do that, we poke another hole in run to completion.

I also suspect such patches will be difficult to maintain. Even if we
update implementations to invoke onresize asynchronously, how
confident can we be in interactions between such unrelated components
as event dispatch and storage continuing to work correctly?

Finally, even with these hacks, we have problems. In a MELUA (I love
that acronym!), with per-origin local storage mutexes, we still can
end up with unresponsive UI because it is possible to have the same
origin running on different event loops.

Adding an asynchronous step to acquire the mutex neatly solves all
these problems. We get run-to-completion, and we never block an event
loop on waiting for a mutex.

On Tue, Sep 8, 2009 at 12:39 PM, Chris Jones<cjones at mozilla.com> wrote:
> I think we all agree that a script may fail to modify localStorage in some
> situations (irrespective of global mutex vs. per-domain mutex). One camp,
> wanting "mutex" semantics, would prefer to pretend that the failures never
> happen and let scripts clean up the mess (partially-applied changes) if they
> do occur.  This is semantically broken, IMHO.
>
> The second camp, wanting "transaction" semantics, explicitly acknowledge to
> web authors that localStorage is fallible, guarantee that modifications to
> localStorage are atomic, and notify scripts when modifications can't be made
> atomically.  This is the same approach taken by Web Database.  IMHO, this is
> much better semantically because (i) it gives web apps stronger guarantees;
> and (ii) it makes the discussion about global mutex/per-domain
> mutex/non-blocking an implementation issue rather semantic issue, as it
> should be.
>
> Can those in the first camp explain why "mutex" semantics is better than
> "transaction" semantics?  And why it's desirable to have one DB spec specify
> "transaction" semantics (Web Database) and a second specify "mutex"
> semantics (localStorage)?

Ok, I don't have a strong preference on this. Transaction semantics
seem better to me, but only marginally so.

- a



More information about the whatwg mailing list