<br><br><div class="gmail_quote">On Tue, Mar 24, 2009 at 2:11 AM, Ian Hickson <span dir="ltr">&lt;ian@hixie.ch&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
I&#39;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 class="im"><br>
<br>
On Fri, 20 Mar 2009, Jeremy Orlow wrote:<br>
&gt;<br>
&gt; Anyhow, the very first example in the spec (<br>
&gt; <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>
&gt; shows work that&#39;s being done in a infinite loop with postMessage being<br>
&gt; called when each prime is found.  If you called localStorage anywhere<br>
&gt; within that loop (say, to periodically save all primes found), you would<br>
&gt; not be able to safely call window.localStorage in any other worker or<br>
&gt; the web page.  This is because the &quot;task that started the script&quot; never<br>
&gt; ends. And this its &#39;lock&#39; (on other scripts using local storage) will<br>
&gt; never be released.<br>
<br>
</div>I&#39;ve removed localStorage from the Web Workers spec for now.<br>
<div class="im"><br>
<br>
On Fri, 20 Mar 2009, Jonas Sicking wrote:<br>
&gt;<br>
&gt; I do think it would be great if workers had access to some type of<br>
&gt; structured storage. However I agree that the fact that both the main<br>
&gt; thread and workers have synchronous access to the same storage is not<br>
&gt; acceptable since that means that we&#39;re violating the<br>
&gt; shared-nothing-message-passing design that makes workers not have to<br>
&gt; 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>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&#39;t not require locking semantics beyond</div><div>the scope of a single scriptable API call... that would be less troubling.</div>
<div><br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>
<div class="im"><br>
<br>
On Fri, 20 Mar 2009, Drew Wilson wrote:<br>
&gt;<br>
&gt; One alternative I&#39;d like to propose is to remove access to localStorage<br>
&gt; for dedicated workers, and give SharedWorkers access to localStorage,<br>
&gt; but have that storage be partitioned by the worker name (i.e. the worker<br>
&gt; can access it, but it&#39;s not shared with web pages or any other workers<br>
&gt; and so you don&#39;t have any synchronicity issues).<br>
<br>
</div>That&#39;s an interesting idea, and would be relatively easy to do. Do people<br>
think it is worth it?</blockquote><div><br></div><div>I think there&#39;s some additional low-hanging fruit too. We&#39;re toying with two,</div><div>independent axis: lifetime vs accessScope.</div><div><br></div><div>  &#39;sessionStorage&#39; has sessionOnlyLifetime and tabSpecificScope</div>
<div>  &#39;localStorage&#39; has persistentLifetime and browserWideScope</div><div><br></div><div>In this nomenclature, the new idea could be phrased as...</div><div><br></div><div>  &#39;page/workerStorage&#39; 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&#39;t make much sense since</div><div>you get a new set of tabs when starting a new session</div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<br>
<div class="im"><br>
<br>
On Fri, 20 Mar 2009, Aaron Boodman wrote:<br>
&gt;<br>
&gt; I think the best option is to make access to localstorage asynchronous<br>
</div>&gt; for workers. This reduces the amount of time a worker can hold the<br>
<div class="im">&gt; localstore lock so that it shouldn&#39;t be a problem for normal pages. It<br>
&gt; sucks to make such a simple and useful API aync though.<br>
<br>
</div>I don&#39;t think making it async helps here, since the problem isn&#39;t that it<br>
is synchronous, but that workers don&#39;t return quickly (by design).<br>
<div class="im"><br>
<br>
On Sat, 21 Mar 2009, Aaron Boodman wrote:<br>
&gt;<br>
&gt; Actually, I don&#39;t believe that it is required that the callback run<br>
&gt; asynchronously. All the callback is used for is establishing the lock<br>
&gt; lifetime explicitly, and we assume that this will usually make the lock<br>
&gt; lifetime short. So we can block while we wait for it to become<br>
&gt; 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 class="im"><br>
<br>
On Sat, 21 Mar 2009, Jonas Sicking wrote:<br>
&gt;<br>
&gt; As I understand the current API (on main window) to be defined, as soon<br>
&gt; as someone accesses the .localStorage property, the implementation is<br>
&gt; supposed to acquire a lock. This lock would be held on to until that<br>
&gt; script returns to the event loop for that thread.<br>
&gt;<br>
&gt; So if javascript in another window, running in another thread or<br>
&gt; process, tries to access .localStorage for the same origin, the<br>
&gt; .localStorage getter would try to acquire the same lock and block until<br>
&gt; the first thread releases the lock.<br>
<br>
</div>Right.<br>
<div class="im"><br>
<br>
On Sat, 21 Mar 2009, Jonas Sicking wrote:<br>
&gt;<br>
&gt; The problem with synchronously grabbing the lock is that we can only<br>
&gt; ever have one feature that uses synchronous locks, otherwise we&#39;ll risk<br>
&gt; dead-locks.<br>
<br>
</div>Indeed. This is a problem with the current API for localStorage in windows<br>
as well.<br>
<br>
I&#39;ve made the spec explicitly have a single shared lock for all features<br>
that need locking (currently just .cookie and .localStorage).<br>
<div class="im"><br>
<br>
On Sun, 22 Mar 2009, Michael Nordman wrote:<br>
&gt;<br>
&gt; Given an async api, would it be possible to store values into<br>
&gt; localStorage at onunload time? I expect that could be a useful time to<br>
&gt; use this API.<br>
&gt;<br>
&gt; function onunload() {<br>
&gt;   getLocalStorage(function(storage) {<br>
&gt;     // Will this ever execute?<br>
&gt;   });<br>
&gt; }<br>
&gt;<br>
&gt; Locking the storage until script completion isn&#39;t really necessary in<br>
&gt; many cases. Maybe we&#39;re over engineering this? Suppose immutability<br>
&gt; across calls was generally not guaranteed by the existing API. And we<br>
&gt; add an async getLocalStorage(callback) which does provide immutability<br>
&gt; 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 class="im"><br>
<br>
On Sun, 22 Mar 2009, Drew Wilson wrote:<br>
&gt;<br>
&gt; The problem is that .length is basically useless without some kind of<br>
&gt; immutability guarantees.<br>
<br>
</div>Indeed.<br>
<div class="im"><br>
<br>
On Sun, 22 Mar 2009, Drew Wilson wrote:<br>
&gt;<br>
&gt; That&#39;s why I&#39;m proposing that the most reasonable implementation is just<br>
&gt; to have a simple lock like I describe above<br>
<br>
</div>This is what I&#39;ve done.<br>
<div class="im"><br>
<br>
&gt; and then either deny access to localStorage to dedicated workers (shared<br>
&gt; workers can silo the storage as I described previously), or else just<br>
&gt; enforce a limit to how long workers can hold the localStorage lock (if<br>
&gt; they hold it beyond some period, they get terminated just like page<br>
&gt; script that doesn&#39;t re-enter the event loop).<br>
<br>
</div>I&#39;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 class="im"><br>
<br>
On Mon, 23 Mar 2009, Jeremy Orlow wrote:<br>
&gt;<br>
&gt; One thing that hasn&#39;t been considered yet is some sort of optional hint<br>
&gt; to say &quot;I&#39;m done&quot; in terms of accessing localStorage.  Maybe call it<br>
&gt; localStorage.checkpoint() or localStroage.commit()?<br>
<br>
</div>Since this applies to more than just storage, I&#39;ve put it on the Navigator<br>
object. I&#39;ve called it releaseLock().<br>
<div class="im"><br>
<br>
On Sat, 21 Mar 2009, Jonas Sicking wrote:<br>
&gt;<br>
&gt; As a side note, if we do go with this async lock acquiring, we could add<br>
&gt; an API like:<br>
&gt;<br>
&gt; getLockedFeatures(callback, &#39;localStore&#39;, &#39;cookie&#39;);<br>
&gt;<br>
&gt; This would be an asynchronously grab locks to multiple features and only<br>
&gt; call the callback once all of them have been acquired. This would allow<br>
&gt; computations across data from multiple locations guaranteed to be in<br>
&gt; sync. The implementation would be responsible for grabbing the locks in<br>
&gt; 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&#39;t really do for cookie (and don&#39;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 class="im"><br>
<br>
On Mon, 23 Mar 2009, Robert O&#39;Callahan wrote:<br>
&gt;<br>
&gt; It has to be resolved in a way that doesn&#39;t expose asynchronous cookie<br>
&gt; or localStorage changes to Web developers. There is abundant evidence<br>
&gt; that race conditions and synchronization are too hard for developers to<br>
&gt; deal with. The spec should forbid asynchronously visible changes to<br>
&gt; cookies or localStorage. In fact, it should probably simply say that all<br>
&gt; script execution is serializable: always equivalent to some execution<br>
&gt; you could get with a single-threaded browser that runs all scripts to<br>
&gt; completion. Allowance could be made for explicit yield points if we need<br>
&gt; 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 class="im"><br>
<br>
&gt; Some sort of implicit locking with guaranteed deadlock freedom should be<br>
&gt; workable for parallel browser implementations. For example, partition<br>
&gt; browser contexts into &quot;related&quot; subsets, where context A is related to<br>
&gt; context B if a script running in context A can affect the execution of<br>
&gt; an already-running script in context B. Use one lock per subset, and<br>
&gt; have a script execution acquire the lock when it first touches<br>
&gt; localStorage or cookies, and drop the lock when it completes (or<br>
&gt; yields). Additional optimizations are possible.<br>
<br>
</div>I&#39;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&#39;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&#39;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>
&lt;iframe&gt;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 class="im"><br>
<br>
On Sat, 21 Mar 2009, Jonas Sicking wrote:<br>
&gt;<br>
&gt; I don&#39;t think it will be a big problem. As long as we ensure that all<br>
&gt; locks are per-origin, that means that an application can only starve<br>
</div>&gt; 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&#39;m sure, lead to pretty awful bugs that authors<br>
wouldn&#39;t understand how to fix. Are we sure we want to go there?<br>
<font color="#888888"><br>
--<br>
Ian Hickson               U+1047E                )\._.,--....,&#39;``.    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.   `._.-(,_..&#39;--(,_..&#39;`-.;.&#39;<br>
</font></blockquote></div><br>