<span class="Apple-style-span" style="border-collapse: collapse; "><div>> sessionLifetime + tabSpecificScope doesn't make much sense since</div><div>> you get a new set of tabs when starting a new session</div><div>
<br></div><div>Sorry...  make that persistentLifetime  + tabScope doesn't make sense.</div><div><br></div></span><br><div class="gmail_quote">On Fri, Mar 27, 2009 at 3:29 PM, Michael Nordman <span dir="ltr"><<a href="mailto:michaeln@google.com">michaeln@google.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br><br><div class="gmail_quote"><div><div></div><div class="h5">On Tue, Mar 24, 2009 at 2:11 AM, Ian Hickson <span dir="ltr"><ian@hixie.ch></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
<br>
I've updated the specs as follows:<br>
<br>
 - removed localStorage from Web Workers for now.<br>
<br>
 - extended the implicit lock mechanism that we had for storage to also<br>
   cover document.cookie, and made the language more explicit about how<br>
   it works.<br>
<br>
 - added navigator.releaseLock().<br>
<div><br>
<br>
On Fri, 20 Mar 2009, Jeremy Orlow wrote:<br>
><br>
> Anyhow, the very first example in the spec (<br>
> <a href="http://dev.w3.org/html5/workers/#a-background-number-crunching-worker" target="_blank">http://dev.w3.org/html5/workers/#a-background-number-crunching-worker</a>)<br>
> shows work that's being done in a infinite loop with postMessage being<br>
> called when each prime is found.  If you called localStorage anywhere<br>
> within that loop (say, to periodically save all primes found), you would<br>
> not be able to safely call window.localStorage in any other worker or<br>
> the web page.  This is because the "task that started the script" never<br>
> ends. And this its 'lock' (on other scripts using local storage) will<br>
> never be released.<br>
<br>
</div>I've removed localStorage from the Web Workers spec for now.<br>
<div><br>
<br>
On Fri, 20 Mar 2009, Jonas Sicking wrote:<br>
><br>
> I do think it would be great if workers had access to some type of<br>
> structured storage. However I agree that the fact that both the main<br>
> thread and workers have synchronous access to the same storage is not<br>
> acceptable since that means that we're violating the<br>
> shared-nothing-message-passing design that makes workers not have to<br>
> deal with locks and other traditional multithread hazards.<br>
<br>
</div>Agreed. The Database API seems well-suited for this, though.</blockquote><div><br></div></div></div><div>Again... its not just workers that are affected by this... speaking as someone</div><div>that works on a multi-threaded browser, this is troubling. If its possible to</div>

<div>spec features that allow script to poke at the world beyond the page</div><div>boundaries in a fashion that doesn't not require locking semantics beyond</div><div>the scope of a single scriptable API call... that would be less troubling.</div>
<div class="im">
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><br>
<div><br>
<br>
On Fri, 20 Mar 2009, Drew Wilson wrote:<br>
><br>
> One alternative I'd like to propose is to remove access to localStorage<br>
> for dedicated workers, and give SharedWorkers access to localStorage,<br>
> but have that storage be partitioned by the worker name (i.e. the worker<br>
> can access it, but it's not shared with web pages or any other workers<br>
> and so you don't have any synchronicity issues).<br>
<br>
</div>That's an interesting idea, and would be relatively easy to do. Do people<br>
think it is worth it?</blockquote><div><br></div></div><div>I think there's some additional low-hanging fruit too. We're toying with two,</div><div>independent axis: lifetime vs accessScope.</div><div><br></div><div>
  'sessionStorage' has sessionOnlyLifetime and tabSpecificScope</div>
<div>  'localStorage' has persistentLifetime and browserWideScope</div><div><br></div><div>In this nomenclature, the new idea could be phrased as...</div><div><br></div><div>  'page/workerStorage' has persistentLifetime and page/workerSpecificScope</div>

<div><br></div><div>Other slots in the matrix formed by these two axis could make sense...</div><div><br></div><div>  sessionLifetime + page/workerSpecificScope</div><div>  sessionLifetime + browserWideScope</div><div><br>

</div><div>sessionLifetime + tabSpecificScope doesn't make much sense since</div><div>you get a new set of tabs when starting a new session</div><div><div></div><div class="h5"><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">

<br>
<div><br>
<br>
On Fri, 20 Mar 2009, Aaron Boodman wrote:<br>
><br>
> I think the best option is to make access to localstorage asynchronous<br>
</div>> for workers. This reduces the amount of time a worker can hold the<br>
<div>> localstore lock so that it shouldn't be a problem for normal pages. It<br>
> sucks to make such a simple and useful API aync though.<br>
<br>
</div>I don't think making it async helps here, since the problem isn't that it<br>
is synchronous, but that workers don't return quickly (by design).<br>
<div><br>
<br>
On Sat, 21 Mar 2009, Aaron Boodman wrote:<br>
><br>
> Actually, I don't believe that it is required that the callback run<br>
> asynchronously. All the callback is used for is establishing the lock<br>
> lifetime explicitly, and we assume that this will usually make the lock<br>
> lifetime short. So we can block while we wait for it to become<br>
> available. This is just like the behavior today without workers.<br>
<br>
</div>Nothing is to stop someone from just having a long callback, though.<br>
<div><br>
<br>
On Sat, 21 Mar 2009, Jonas Sicking wrote:<br>
><br>
> As I understand the current API (on main window) to be defined, as soon<br>
> as someone accesses the .localStorage property, the implementation is<br>
> supposed to acquire a lock. This lock would be held on to until that<br>
> script returns to the event loop for that thread.<br>
><br>
> So if javascript in another window, running in another thread or<br>
> process, tries to access .localStorage for the same origin, the<br>
> .localStorage getter would try to acquire the same lock and block until<br>
> the first thread releases the lock.<br>
<br>
</div>Right.<br>
<div><br>
<br>
On Sat, 21 Mar 2009, Jonas Sicking wrote:<br>
><br>
> The problem with synchronously grabbing the lock is that we can only<br>
> ever have one feature that uses synchronous locks, otherwise we'll risk<br>
> dead-locks.<br>
<br>
</div>Indeed. This is a problem with the current API for localStorage in windows<br>
as well.<br>
<br>
I've made the spec explicitly have a single shared lock for all features<br>
that need locking (currently just .cookie and .localStorage).<br>
<div><br>
<br>
On Sun, 22 Mar 2009, Michael Nordman wrote:<br>
><br>
> Given an async api, would it be possible to store values into<br>
> localStorage at onunload time? I expect that could be a useful time to<br>
> use this API.<br>
><br>
> function onunload() {<br>
>   getLocalStorage(function(storage) {<br>
>     // Will this ever execute?<br>
>   });<br>
> }<br>
><br>
> Locking the storage until script completion isn't really necessary in<br>
> many cases. Maybe we're over engineering this? Suppose immutability<br>
> across calls was generally not guaranteed by the existing API. And we<br>
> add an async getLocalStorage(callback) which does provide immutability<br>
> for the duration of the callback if that is desired.<br>
<br>
</div>The problem is that people will walk into race conditions without<br>
realising it, and they are amongst the hardest problems to debug.<br>
<div><br>
<br>
On Sun, 22 Mar 2009, Drew Wilson wrote:<br>
><br>
> The problem is that .length is basically useless without some kind of<br>
> immutability guarantees.<br>
<br>
</div>Indeed.<br>
<div><br>
<br>
On Sun, 22 Mar 2009, Drew Wilson wrote:<br>
><br>
> That's why I'm proposing that the most reasonable implementation is just<br>
> to have a simple lock like I describe above<br>
<br>
</div>This is what I've done.<br>
<div><br>
<br>
> and then either deny access to localStorage to dedicated workers (shared<br>
> workers can silo the storage as I described previously), or else just<br>
> enforce a limit to how long workers can hold the localStorage lock (if<br>
> they hold it beyond some period, they get terminated just like page<br>
> script that doesn't re-enter the event loop).<br>
<br>
</div>I've removed the localStorage API from workers.<br>
<br>
Terminating the script like that would be really hard to debug also --<br>
especially since it would end up terminating differently on different<br>
computers (e.g. a desktop might execute the whole initialisation code in<br>
the time alloted, while slower mobile devices might execute only the first<br>
part and the worker would be in an unstable state).<br>
<div><br>
<br>
On Mon, 23 Mar 2009, Jeremy Orlow wrote:<br>
><br>
> One thing that hasn't been considered yet is some sort of optional hint<br>
> to say "I'm done" in terms of accessing localStorage.  Maybe call it<br>
> localStorage.checkpoint() or localStroage.commit()?<br>
<br>
</div>Since this applies to more than just storage, I've put it on the Navigator<br>
object. I've called it releaseLock().<br>
<div><br>
<br>
On Sat, 21 Mar 2009, Jonas Sicking wrote:<br>
><br>
> As a side note, if we do go with this async lock acquiring, we could add<br>
> an API like:<br>
><br>
> getLockedFeatures(callback, 'localStore', 'cookie');<br>
><br>
> This would be an asynchronously grab locks to multiple features and only<br>
> call the callback once all of them have been acquired. This would allow<br>
> computations across data from multiple locations guaranteed to be in<br>
> sync. The implementation would be responsible for grabbing the locks in<br>
> a consistent order to prevent deadlocks.<br>
<br>
</div>Why would we want more than one lock? Is the potential performance gain<br>
worth the complexity?<br>
<br>
The problem with going with an async approach is that it means changing<br>
the API, which is something we can't really do for cookie (and don't<br>
really want to do for localStorage, since IE8 has shipped it.) We we are<br>
going to need a synchronous locking mechanism anyway.<br>
<div><br>
<br>
On Mon, 23 Mar 2009, Robert O'Callahan wrote:<br>
><br>
> It has to be resolved in a way that doesn't expose asynchronous cookie<br>
> or localStorage changes to Web developers. There is abundant evidence<br>
> that race conditions and synchronization are too hard for developers to<br>
> deal with. The spec should forbid asynchronously visible changes to<br>
> cookies or localStorage. In fact, it should probably simply say that all<br>
> script execution is serializable: always equivalent to some execution<br>
> you could get with a single-threaded browser that runs all scripts to<br>
> completion. Allowance could be made for explicit yield points if we need<br>
> to, e.g. alert().<br>
<br>
</div>Generally speaking I have tried to maintain this invariant, but I have<br>
failed with cookies, and with localStorage in workers.<br>
<div><br>
<br>
> Some sort of implicit locking with guaranteed deadlock freedom should be<br>
> workable for parallel browser implementations. For example, partition<br>
> browser contexts into "related" subsets, where context A is related to<br>
> context B if a script running in context A can affect the execution of<br>
> an already-running script in context B. Use one lock per subset, and<br>
> have a script execution acquire the lock when it first touches<br>
> localStorage or cookies, and drop the lock when it completes (or<br>
> yields). Additional optimizations are possible.<br>
<br>
</div>I've updated the spec to require the locking mechanism that was in place<br>
for storage for cookies as well. This still means that one window can<br>
block all other windows that try to use cookies, though, so I've also<br>
added navigator.releaseLock() which can be called to explicitly release<br>
the lock that is put in place.<br>
<br>
User agents that share event loops between origins can't actually have any<br>
more than one lock total. Consider a case where there are three windows<br>
from three different origins, A, B, and C, where C contains a couple of<br>
<iframe>s, and where A, B, and C are independent, but C share an event<br>
loop with whatever content is in its iframes. (This is the situation<br>
Chrome and IE are in, as I understand it, with event loops being<br>
per-window not per-origin, and it may be required because access to the<br>
frames[] hierarchy is synchronous.) Now, assume A and B have both obtained<br>
their respective locks, and are busy doing some long script. C is free to<br>
run more tasks from its event loop, which could include navigating one<br>
iframe to a page on either A and the other iframe to a page on B, meaning<br>
that the event loop of C is now beholden to two locks. If there is any<br>
manner in which to synchronously cause another origin to run script, this<br>
now means that C can attempt to obtain both locks; if we now imagine<br>
another window just like C that instead obtains the locks in the reverse<br>
order, we get deadlock.<br>
<br>
If it can be shown that it is not ever possible for script in one origin<br>
to synchronously invoke script in another origin, then I guess we could<br>
have per-origin locks instead of a single lock.<br>
<div><br>
<br>
On Sat, 21 Mar 2009, Jonas Sicking wrote:<br>
><br>
> I don't think it will be a big problem. As long as we ensure that all<br>
> locks are per-origin, that means that an application can only starve<br>
</div>> itself [using workers]. Something that it has clear incentives not to.<br>
<br>
It can starve itself and anyone that it is related to, which is a problem;<br>
but it would also, I'm sure, lead to pretty awful bugs that authors<br>
wouldn't understand how to fix. Are we sure we want to go there?<br>
<font color="#888888"><br>
--<br>
Ian Hickson               U+1047E                )\._.,--....,'``.    fL<br>
<a href="http://ln.hixie.ch/" target="_blank">http://ln.hixie.ch/</a>       U+263A                /,   _.. \   _\  ;`._ ,.<br>
Things that are impossible just take longer.   `._.-(,_..'--(,_..'`-.;.'<br>
</font></blockquote></div></div></div><br>
</blockquote></div><br>