On Tue, Mar 24, 2009 at 10:11 PM, Ian Hickson <span dir="ltr">&lt;ian@hixie.ch&gt;</span> wrote:<br><div class="gmail_quote"><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

 
- 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.</blockquote><div><br>That&#39;s basically good. It&#39;s possible that people might want to implement something that&#39;s equivalent to the storage mutex in observable behaviour, but allows more parallelism, such as speculative execution or finer-grained locking when the implementation can prove it&#39;s safe. I assume implementors of HTML5 already understand that that&#39;s allowed.<br>

<br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">- added navigator.releaseLock().<br>
<div></div></blockquote><div><br>This name could be confusing to developers, because there is no corresponding explicit acquireLock(), which there usually is in an API that exposes releaseLock().<br><br>navigator.allowInterruption() maybe?<br>

<br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">On Sat, 21 Mar 2009, Jonas Sicking wrote:<br><div>
&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.</blockquote><div><br>It would be possible to use something like getLockedFeatures for workers while using implicit locking for the main thread.<br><br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">

On Mon, 23 Mar 2009, Robert O&#39;Callahan wrote:<br><div>
&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.</blockquote><div><br>Now, with the storage mutex, are there any cases you know of where serializability fails? If there are, it may be worth noting them in the spec. If there aren&#39;t, why not simply write serializability into the spec?<br>

<br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">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.</blockquote><div><br>Interesting example!<br><br>When two sets of unrelated browser contexts become related (e.g., C loads A into an iframe), I imagined you would join A&#39;s lock and C&#39;s lock into a single lock covering the new set of related browser contexts, which is safe to do if at most one of those locks is currently held. When this happens due to a document being created with origin A in C&#39;s iframe, it happens asynchronously in C, right? So at that point C&#39;s lock is not held by currently running script in C (although it might be held by code in another domain which is already related to C), and we can block the join operation in C until one of the two locks is released.<br>
<br>Then in your example, suppose C loads A&#39;s document first. Then C&#39;s lock and A&#39;s lock are joined to make a CA-lock. Then suppose D (&quot;another window just like C&quot;) loads B&#39;s document; D&#39;s lock and B&#39;s lock are merged to make the DB-lock. Now suppose C loads B. The two remaining locks are merged to form a single CADB-lock. No deadlock is possible.<br>
<br></div><blockquote class="gmail_quote" style="margin: 0pt 0pt 0pt 0.8ex; border-left: 1px solid rgb(204, 204, 204); padding-left: 1ex;">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></div></blockquote><br>I&#39;m not sure why synchronous invocation across origins matters. I think what matters here is whether there&#39;s a synchronous operation that can cause two browsing contexts to become related that previously weren&#39;t. If there is, then the above approach would break down; a script in A could get A&#39;s lock and then attempt to join with C, while a script in C could get C&#39;s lock and then attempt to join with A. I can&#39;t think of such a case though.<br>
<br clear="all"></div>Rob<br>-- <br>&quot;He was pierced for our transgressions, he was crushed for our iniquities; the punishment that brought us peace was upon him, and by his wounds we are healed. We all, like sheep, have gone astray, each of us has turned to his own way; and the LORD has laid on him the iniquity of us all.&quot; [Isaiah 53:5-6]<br>