<?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>288682</bug_id>
          
          <creation_ts>2025-02-26 20:29:12 -0800</creation_ts>
          <short_desc>IndexedDB in Worker commits when thread is terminated</short_desc>
          <delta_ts>2025-03-27 15:36:40 -0700</delta_ts>
          <reporter_accessible>1</reporter_accessible>
          <cclist_accessible>1</cclist_accessible>
          <classification_id>1</classification_id>
          <classification>Unclassified</classification>
          <product>WebKit</product>
          <component>New Bugs</component>
          <version>Safari Technology Preview</version>
          <rep_platform>Mac (Apple Silicon)</rep_platform>
          <op_sys>macOS 15</op_sys>
          <bug_status>RESOLVED</bug_status>
          <resolution>FIXED</resolution>
          
          
          <bug_file_loc></bug_file_loc>
          <status_whiteboard></status_whiteboard>
          <keywords>InRadar</keywords>
          <priority>P1</priority>
          <bug_severity>Major</bug_severity>
          <target_milestone>---</target_milestone>
          
          
          <everconfirmed>1</everconfirmed>
          <reporter>neil</reporter>
          <assigned_to name="Sihui Liu">sihui_liu</assigned_to>
          <cc>webkit-bug-importer</cc>
    
    <cc>wilander</cc>
          

      

      

      

          <comment_sort_order>oldest_to_newest</comment_sort_order>  
          <long_desc isprivate="0" >
    <commentid>2098591</commentid>
    <comment_count>0</comment_count>
      <attachid>474365</attachid>
    <who name="">neil</who>
    <bug_when>2025-02-26 20:29:12 -0800</bug_when>
    <thetext>Created attachment 474365
Testcase to reproduce transaction commit on worker termination

# Summary

When a worker thread running an indexedDB transaction is terminated, WebKit can *commit* the half-complete transaction rather than aborting. This makes transactions, well, non-transactional, which can cause severe data corruption.

# Background

We are building full offline support into the [Fastmail](https://www.fastmail.com/) web app. Our iOS app is essentially a WKWebView-based wrapper around the same. Data is stored in indexedDB, which runs inside a web worker (shared worker for web browsers, normal worker for our app where we know there can only ever be one UI instance). If interested/relevant, more details of the architecture can be found in [this blog post](https://www.fastmail.com/blog/offline-architecture/).

We have noticed some iOS beta testers getting corrupt databases. Inspecting the data we found it was consistent with a transaction having been abandoned half-way through, but the data written up to that point being committed. To test this theory we added a patch so that for every transaction:

1. We insert a sentinel record into the DB
2. We do the operations in the transaction
3. We remove the sentinel record from the DB
4. We commit the transaction

This should mean the sentinel record is never committed to the DB. We then added a check before (1) for the sentinel record. If it was present, we knew a transaction had been abandoned but committed. Sure enough, we started getting occasional hits, solely from WebKit. Looking at the logs, it seemed to coincide with the page being reloaded. It looks like the worker is being terminated while in the middle of a transaction, but rather than aborting the transaction as it should it&apos;s *committing* what&apos;s been written so far.

I have managed to produce a test case that shows this behaviour. Note, in this test case I am explicitly terminating the worker, which makes it very reproducible, but we were seeing this sporadically even when not doing so — I presume because the OS was terminating the worker on page reload, perhaps with some short timeout. Not too, if you *remove* the `worker.terminate()` from the test case you see another bug: on the page after reload we can never establish a successful connection to the DB. All requests to it hang.

# Steps to reproduce

1. Open https://testcases.fastmail.io/webkit-commit/idb-bug.html
2. Click &quot;Run test&quot;
3. Expected result: &quot;Passed&quot;. Actual result: &quot;Failed&quot;.

I&apos;ve also attached the testcase; the files are the same.

# Request for advice on workaround

Obviously we would like to see this fixed, however given the release cycle of iOS we don&apos;t want to have to wait for this fix to be present before releasing our offline support. So far we are struggling to find a 100% reliable way of avoiding the bug, as the OS can terminate the worker and cause the issue. I&apos;m hoping that someone with understanding of the WebKit code and the root cause of this might be able to suggest some way we can avoid this issue in the meantime. Thanks for any help!</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2100861</commentid>
    <comment_count>1</comment_count>
    <who name="Radar WebKit Bug Importer">webkit-bug-importer</who>
    <bug_when>2025-03-05 20:30:14 -0800</bug_when>
    <thetext>&lt;rdar://problem/146354005&gt;</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2105163</commentid>
    <comment_count>2</comment_count>
    <who name="John Wilander">wilander</who>
    <bug_when>2025-03-21 16:01:53 -0700</bug_when>
    <thetext>Thanks for the report, Neil! I&apos;ll ping the right folks.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2105818</commentid>
    <comment_count>3</comment_count>
    <who name="Sihui Liu">sihui_liu</who>
    <bug_when>2025-03-24 23:12:55 -0700</bug_when>
    <thetext>Basically transaction will be automatically committed when there is no more request scheduled on the transaction, and requests can be scheduled when transaction is created and when even is being dispatched. That is, if transaction has been created (control has returned to event loop after transaction creation) and there is no more event to be dispatched, the transaction will be committed automatically.

Technically new requests can be scheduled within macro task (e.g. event handlers like `onsuccess`) and micro task (e.g. Promise resolve function). Looks like there is an issue in the Worker termination case where WebKit does not perform micro tasks (not create requests in resolve function of Promise), so it ends up thinking there is no more request and automatically committing transaction.

I think a workaround should be to use event handler to schedule request directly instead of relying on Promise. For example, you may use a helper function like:
function keepTransactionActive(transaction) {
    if (!shouldKeepTransactionActive)
        return;
    const request = transaction.objectStore(&quot;foo&quot;).get(&quot;test&quot;);
    request.onsuccess = (event) =&gt; { keepTransactionActive(event.target.transaction); };
}</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2106042</commentid>
    <comment_count>4</comment_count>
    <who name="">neil</who>
    <bug_when>2025-03-25 17:54:56 -0700</bug_when>
    <thetext>Ah, interesting, thanks for the detail. I&apos;ll give that workaround a go and see if that can prevent the issue until the underlying bug is fixed.</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2106198</commentid>
    <comment_count>5</comment_count>
    <who name="Sihui Liu">sihui_liu</who>
    <bug_when>2025-03-26 12:04:10 -0700</bug_when>
    <thetext>Pull request: https://github.com/WebKit/WebKit/pull/43050</thetext>
  </long_desc><long_desc isprivate="0" >
    <commentid>2106606</commentid>
    <comment_count>6</comment_count>
    <who name="EWS">ews-feeder</who>
    <bug_when>2025-03-27 15:36:38 -0700</bug_when>
    <thetext>Committed 292795@main (b9d8178a0635): &lt;https://commits.webkit.org/292795@main&gt;

Reviewed commits have been landed. Closing PR #43050 and removing active labels.</thetext>
  </long_desc>
      
          <attachment
              isobsolete="0"
              ispatch="0"
              isprivate="0"
          >
            <attachid>474365</attachid>
            <date>2025-02-26 20:29:12 -0800</date>
            <delta_ts>2025-02-26 20:29:12 -0800</delta_ts>
            <desc>Testcase to reproduce transaction commit on worker termination</desc>
            <filename>idb-commit-bug.zip</filename>
            <type>application/zip</type>
            <size>2607</size>
            <attacher>neil</attacher>
            
              <data encoding="base64">UEsDBBQACAAIAMh4W1oAAAAAAAAAAFATAAARACAAaWRiLWJ1Zy13b3JrZXIuanNVVA0AB7jkv2eC
5b9ngOW/Z3V4CwABBPUBAAAEFAAAAK1XTXPbNhC961egvBhyRMq+WlEObWY6PbjJjJv2kMl0IBKS
2FKAQoCWXQ//e3cBkARJiFYy4UUSuLvYj7dvV8trwlWRCx1nuWKbghMh40pkfEuul7NZWjClyHum
2YYpTl5mBJ7lkgh24HdE6TIXu+bskZcql+KOiOqw4WVzrLiujneEZpuFLLI/rdBC8JP7OjeCqRRg
rUq1LOkhf8rF3F2Gj97nKvk725A12C6K1eCFLplQLNVgTKEIP5EHrum8k/uw+YenOoFY8p2gqLUg
9hYrU8/MhzxyQf2L8y2hzeX+OT4lxFWK1rfusrr9ZoIiznHw6mMpD7nilJZcyeKRL8AIOjYn63cD
61YV0wy65g78vgrIlPxrxeFzTXIo2xPP3v+cmEBQYWF1XWnmq0EERjORojruSpZxwXnGM7BE+SMX
Ibe6a01QjQWIpyr0aiRqLjcAoKN3+AAmgufm+qTDyJSUB6qgVOOjh5KR3CAx9bk8qSpNuUKQ0R+U
HGmQ+QCw579DvdB0thmdjpVRSKSFVHzCGXx8CJP1ek0CUB55Feq1XoJGp/VY0IEcGv/S9PKylGUb
j+0N2rw2Lz1Ltfcd/E1SptM9DaXi0hRMhl4HL/ZUehzgyKE9cwQDdHgvM27AwbJTmWtOIGL8IUXx
bGSYehYp8dBKVYsDYC1QX5Btjx49zLETy7VDliGzziXMwk+dqWEClA/BIDRDDAcB9cdHLPiTjuHE
DBITS3y0tBcDOaUVmBtmyadGG/3FBOmlyXbOVN4GMBwPj4RlGfUOhgrdGwAr28hSTzSfg6+vNISw
yeXUHak8HAuup3q86bLXzD4HdC1atmIi5jOJyji69ZqeFwtEcsj1yEtiuhbmjcnM+SyGMvejXDOF
HHk2anfXwhaghnnpuAktFYx3Amy+AOtMMs6orXsW8UHWs44Me7OegbvOJQSPI1HEkHn/DdsIut6N
MpY9P2iGiAQejYC1eDQMyld4ra7nyN3EQHjR7px9XQv5/oA9W0CrgkwTYrDzw/3Va75jcCGYZkCa
cRw39Wm3w2bLpjZiu2JHDBgztt0TazAX2S2nXbZv7W+7ZAFCFsRbm4i3HPmY9ytiZicUVvMPHeHT
aCtl1Di9mBm/t5WwTJvu+emXj5/+yA8w3auS+SZtUEozQ44QE0+EPDUIPe1z+ItBu2MSO9m3ZGgJ
n3um94n6Cv1pvkEEmTzQeduSgHLbkK1vZqhiKtvutM0zmA3YbgsStWM4WrjO7hFHvxMwNFnwpJA7
Gv0m/IRGHixcs/aYX45SmxwrTV9q8EHAHlvaCkdzzw7QGPwjQTx+/tKdbgFoFF/l8OJmBR9vya35
fLMmt8NW8yt1e3NzMx9TTBvRX5AH+DsH8E1lmZGIvCH5QB7cAb/Vnl4e3X8bVlpT8+nLJZDKmavr
QW4dcyWsKCi49O25dzMimHqEOsBK8WILnQ3Lg2I7HMAOHi8kA3DdQSpAssMHVsRf9JEEQcSwpD1X
0XBctMH/yrXLvBMcBjQA72cTxheHX9wcL4Fv151eRnBaTeaqXzMMc1exMrtkvTCC3fSinvFkB3/Q
zyLflKFbDcITxM9gcHyMhpLxJzyMMO/gabRleRFdPoac1pEpNdTq7Q/tD4Oqo1T63uKK9oZKPYLO
Tp5HTdOviEe/TuNi2AJ4zNj3FeaRlRDsMd8xqA9ckP6rEjfB6FAanysUuVqEXr2EDvHBJfyOXKk9
K3kW1q2Dpw7by2uCt5LrZQDaZw34RDK5b04hqg7XwC5A7TRazf4HUEsHCD0AsVgwBQAAUBMAAFBL
AwQUAAgACAA4eVtaAAAAAAAAAACFAgAADAAgAGlkYi1idWcuaHRtbFVUDQAHjOW/Z4zlv2eM5b9n
dXgLAAEE9QEAAAQUAAAAZZLBbtswDIbveQrOwJCLVafDDkMm+9B2xXrYMjTNYUfZoR22kmxYVBZv
2LuPjtM1aHWQoI/kD/4E9bub1fXDzx9fYMfOFjP9/KDZFjOQox2ygWpn+oCcJ5uHW/UpgewUZGKL
xd3NFVStc8RQxkZnEz0r98ZhnuwJf3Vtz4kke0Yvco48uehUqIzF/PJikYIzh9dIkpiMPUcxYH/8
m1KQb1N4Vlc1cV61e+xf2gw8SEOjtxTKdjvAnyMfz5ZCZ82whNri4fN//BgDUz2oU6dLqOTG/iXB
WGq8IkYX3gZrqVK1cWRFOAxBslSkFJTpOotqIilcWfJP30y1Pv5vpSiF+RqbFmFzN0/hvi1bFmur
w9CgT2FTRs8xhWvj2fRoxc181aGHtfFB8udf0e6RqTLwHSMKCRJQMiqqXzUX6Dcu4cPH7szzDqnZ
idXLxeL9RP/qbBrdTGfTSuhxfOMTmVtf3EcPjIF1dgIzHaqeOobQV3lC21LJRlw8hqQQqWNk1DqJ
ZNO2/QNQSwcIsWoD9oUBAACFAgAAUEsDBBQACAAIADl5W1oAAAAAAAAAAJkCAAAKACAAaWRiLWJ1
Zy5qc1VUDQAHj+W/Z5Hlv2eP5b9ndXgLAAEE9QEAAAQUAAAAjZHPTsMwDMbvfQorp1SwDq5MhRtw
YBISkzinqdeFtclIXE3TVImn4cF4Etw/G9XQEL45tn+Ov087Gwi2zq/RQwoWt/DaJVIkU5Nnk6wu
Jn05eQsCLqB0WpFxNgmovF7Fs2goO1thCKpA5sg95IrUDbgNNDGkt7CPgMMsQfJTmqYgNioEEQ+F
NnKn6wotJZnLd4mxFv3jYv7EOPHMvZiLWdfb/EItlSn/i7rn3hGqmUUtaeox1CWFaUIYSB6PXHlc
xgfycOjGBZr3p0oxzIm4B/6x+AGJjC2gn/j6+OQ/NIBlwAGvOy+ymshZHjii3mv0uxcsUZNjX/qG
w8I+Y/F1afS6lX4k97lPF+4wPkLkJqiMpWEG+Rp/6gFpYSp0NclT+GgBoa+MVYRyhG7jqCV7aAor
xd2JZp0Rl3B9NeRsSRN9A1BLBwg7QoBOQgEAAJkCAABQSwECFAMUAAgACADIeFtaPQCxWDAFAABQ
EwAAEQAgAAAAAAAAAAAApIEAAAAAaWRiLWJ1Zy13b3JrZXIuanNVVA0AB7jkv2eC5b9ngOW/Z3V4
CwABBPUBAAAEFAAAAFBLAQIUAxQACAAIADh5W1qxagP2hQEAAIUCAAAMACAAAAAAAAAAAACkgY8F
AABpZGItYnVnLmh0bWxVVA0AB4zlv2eM5b9njOW/Z3V4CwABBPUBAAAEFAAAAFBLAQIUAxQACAAI
ADl5W1o7QoBOQgEAAJkCAAAKACAAAAAAAAAAAACkgW4HAABpZGItYnVnLmpzVVQNAAeP5b9nkeW/
Z4/lv2d1eAsAAQT1AQAABBQAAABQSwUGAAAAAAMAAwARAQAACAkAAAAA
</data>

          </attachment>
      

    </bug>

</bugzilla>