<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<!DOCTYPE bugzilla SYSTEM "https://bugs.webkit.org/page.cgi?id=bugzilla.dtd">

<bugzilla version="5.0.4.1"
          urlbase="https://bugs.webkit.org/"
          
          maintainer="admin@webkit.org"
>

    <bug>
          <bug_id>233980</bug_id>
          
          <creation_ts>2021-12-07 22:33:32 -0800</creation_ts>
          <short_desc>A dedicated worker is not frozen even when the page is in back/forward cache</short_desc>
          <delta_ts>2021-12-09 14:42:06 -0800</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>WebKit Misc.</component>
          <version>Safari 15</version>
          <rep_platform>Unspecified</rep_platform>
          <op_sys>Unspecified</op_sys>
          <bug_status>NEW</bug_status>
          <resolution></resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>InRadar</keywords>
          <priority>P2</priority>
          <bug_severity>Normal</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter name="Hajime Hoshi">hajimehoshi</reporter>
          <assigned_to name="Nobody">webkit-unassigned</assigned_to>
          <cc>achristensen</cc>
    
    <cc>ap</cc>
    
    <cc>cdumez</cc>
    
    <cc>fpizlo</cc>
    
    <cc>ggaren</cc>
    
    <cc>mark.lam</cc>
    
    <cc>nham</cc>
    
    <cc>webkit-bug-importer</cc>
    
    <cc>youennf</cc>
    
    <cc>ysuzuki</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>1821399</commentid>
    <comment_count>0</comment_count>
    <who name="Hajime Hoshi">hajimehoshi</who>
    <bug_when>2021-12-07 22:33:32 -0800</bug_when>
    <thetext>Reproducing steps:

1. Open https://hajimehoshi.github.io/sandbox/worker/
2. See the numbers for a while
  There are two counters. The upper is counted by the main frame and the lower is counted by a dedicated worker.
3. Click &apos;Google.com&apos;
4. Stay for a while (10 seconds or so)
5. Go back to the original page. The worker counter is increased for the time duration of being in google.com.

Source code: https://github.com/hajimehoshi/sandbox/tree/main/worker</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822183</commentid>
    <comment_count>1</comment_count>
    <who name="Chris Dumez">cdumez</who>
    <bug_when>2021-12-09 10:39:48 -0800</bug_when>
    <thetext>The issue is that this worker thread is busy looping and thus never processing the message from the main thread asking it to suspend.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822186</commentid>
    <comment_count>2</comment_count>
    <who name="Geoffrey Garen">ggaren</who>
    <bug_when>2021-12-09 10:43:08 -0800</bug_when>
    <thetext>Maybe the suspend message should kill the worker if there&apos;s no timely reply.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822188</commentid>
    <comment_count>3</comment_count>
    <who name="Chris Dumez">cdumez</who>
    <bug_when>2021-12-09 10:44:52 -0800</bug_when>
    <thetext>(In reply to Geoffrey Garen from comment #2)
&gt; Maybe the suspend message should kill the worker if there&apos;s no timely reply.

We could do that. I was thinking about calling WTF::Thread::suspend() instead of posting a message to the thread. Any opposition to that?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822191</commentid>
    <comment_count>4</comment_count>
    <who name="Alexey Proskuryakov">ap</who>
    <bug_when>2021-12-09 10:48:23 -0800</bug_when>
    <thetext>Would it suspend threads holding mutexes, and freeze the main thread as a consequence?</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822192</commentid>
    <comment_count>5</comment_count>
    <who name="Chris Dumez">cdumez</who>
    <bug_when>2021-12-09 10:49:56 -0800</bug_when>
    <thetext>(In reply to Alexey Proskuryakov from comment #4)
&gt; Would it suspend threads holding mutexes, and freeze the main thread as a
&gt; consequence?

You&apos;re right, I think that would be a risk indeed and very likely the reason why our suspension logic currently works the way it does.

I guess timeout + kill is the way to go then.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822199</commentid>
    <comment_count>6</comment_count>
    <who name="Geoffrey Garen">ggaren</who>
    <bug_when>2021-12-09 11:00:18 -0800</bug_when>
    <thetext>In my suggestion to &quot;kill the worker&quot;, I had assumed this was a ServiceWorker. But I see now that it&apos;s just a Worker.

It&apos;s an interesting edge case because there&apos;s no plain definition of &quot;kill&quot;. Should we exit the process and possibly take down other pages with us?

I wonder if the right behavior is just to wait synchronously for the worker to terminate. Then, if the worker is hung, you get the same behavior you would have gotten if the main thread were hung. In practice, that might often trigger some kind of watchdog kill. Or something else.

It seems to me that modeling this like a hang of the main thread might be the most accurate thing, if that&apos;s possible.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822224</commentid>
    <comment_count>7</comment_count>
    <who name="Alexey Proskuryakov">ap</who>
    <bug_when>2021-12-09 11:20:29 -0800</bug_when>
    <thetext>There are other cases where dedicated workers are supposed to be paused or terminated (see https://html.spec.whatwg.org/multipage/workers.html#terminate-a-worker and around). E.g. I don&apos;t think that we are allowed to let it spin once it&apos;s no longer observable in an active page either.

I think that it&apos;s mostly implemented in WebKit, but have been out of the loop for too long to point it out.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822292</commentid>
    <comment_count>8</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2021-12-09 13:13:20 -0800</bug_when>
    <thetext>&lt;rdar://problem/86287415&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822313</commentid>
    <comment_count>9</comment_count>
    <who name="Yusuke Suzuki">ysuzuki</who>
    <bug_when>2021-12-09 13:32:42 -0800</bug_when>
    <thetext>(In reply to Chris Dumez from comment #5)
&gt; (In reply to Alexey Proskuryakov from comment #4)
&gt; &gt; Would it suspend threads holding mutexes, and freeze the main thread as a
&gt; &gt; consequence?
&gt; 
&gt; You&apos;re right, I think that would be a risk indeed and very likely the reason
&gt; why our suspension logic currently works the way it does.
&gt; 
&gt; I guess timeout + kill is the way to go then.

Yes. One example is that malloc can have a global mutex for the slow path (e.g. stealing a page from the global heap instead of thread local heap). If we suspend a thread holding that mutex, most likely, soon, the other threads will be blocked once malloc happens.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822316</commentid>
    <comment_count>10</comment_count>
    <who name="Mark Lam">mark.lam</who>
    <bug_when>2021-12-09 13:39:14 -0800</bug_when>
    <thetext>(In reply to Yusuke Suzuki from comment #9)
&gt; (In reply to Chris Dumez from comment #5)
&gt; &gt; (In reply to Alexey Proskuryakov from comment #4)
&gt; &gt; &gt; Would it suspend threads holding mutexes, and freeze the main thread as a
&gt; &gt; &gt; consequence?
&gt; &gt; 
&gt; &gt; You&apos;re right, I think that would be a risk indeed and very likely the reason
&gt; &gt; why our suspension logic currently works the way it does.
&gt; &gt; 
&gt; &gt; I guess timeout + kill is the way to go then.
&gt; 
&gt; Yes. One example is that malloc can have a global mutex for the slow path
&gt; (e.g. stealing a page from the global heap instead of thread local heap). If
&gt; we suspend a thread holding that mutex, most likely, soon, the other threads
&gt; will be blocked once malloc happens.

We can use a mechanism similar to global GC&apos;s stop thread mechanism (doesn&apos;t exist yet) and stop the target thread at a GC consistent point.  Doing so ensure that the target thread won&apos;t be in the middle of any malloc operation.  That said, it doesn&apos;t guarantee yet that there won&apos;t be other locks that could be held.

If suspension is something we think we need, I can consider it in my GC work.  I think with a some work, it is achievable.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822319</commentid>
    <comment_count>11</comment_count>
    <who name="Geoffrey Garen">ggaren</who>
    <bug_when>2021-12-09 13:50:50 -0800</bug_when>
    <thetext>Technically the web standard makes reference to a behavior much more like JSC::Watchdog / JSC::VM::throwTerminationException().

For this case, I think just waiting for termination, combined with our process model, will get the job done.

For the more challenging case of explicitly calling Worker.terminate() in the middle of an infinite loop, I guess we&apos;ll eventually need to adopt / add support for JSC::VM::throwTerminationException() in Worker scripts.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822338</commentid>
    <comment_count>12</comment_count>
    <who name="Alexey Proskuryakov">ap</who>
    <bug_when>2021-12-09 14:30:24 -0800</bug_when>
    <thetext>(In reply to Geoffrey Garen from comment #11)
&gt; Technically the web standard makes reference to a behavior much more like
&gt; JSC::Watchdog / JSC::VM::throwTerminationException().

Exactly what I&apos;ve been vaguely recalling, yes - see WorkerOrWorkletScriptController::scheduleExecutionTermination().</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822344</commentid>
    <comment_count>13</comment_count>
    <who name="Mark Lam">mark.lam</who>
    <bug_when>2021-12-09 14:40:40 -0800</bug_when>
    <thetext>(In reply to Geoffrey Garen from comment #11)
&gt; For the more challenging case of explicitly calling Worker.terminate() in
&gt; the middle of an infinite loop, I guess we&apos;ll eventually need to adopt / add
&gt; support for JSC::VM::throwTerminationException() in Worker scripts.

We already do: Worker.terminate() uses the VMTraps mechanism, which allows a worker to terminate while in an infinite loop.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>1822348</commentid>
    <comment_count>14</comment_count>
    <who name="Geoffrey Garen">ggaren</who>
    <bug_when>2021-12-09 14:42:06 -0800</bug_when>
    <thetext>Maybe it&apos;s a simple fix just to use VMTraps for shutdown too?</thetext>
  </long_desc>
      
      

    </bug>

</bugzilla>