Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make all FileSystemSyncAccessHandle methods sync #7972

Conversation

szewai
Copy link
Contributor

@szewai szewai commented Dec 21, 2022

acd30cd

Make all FileSystemSyncAccessHandle methods sync
https://bugs.webkit.org/show_bug.cgi?id=247071
rdar://problem/101620396

Reviewed by Youenn Fablet.

To match latest spec: https://fs.spec.whatwg.org/#api-filesystemsyncaccesshandle. Chrome has already shipped it.

* LayoutTests/imported/w3c/web-platform-tests/fs/FileSystemSyncAccessHandle-close.https.tentative.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/fs/FileSystemSyncAccessHandle-flush.https.tentative.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/fs/FileSystemSyncAccessHandle-getSize.https.tentative.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/fs/FileSystemSyncAccessHandle-truncate.https.tentative.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/fs/idlharness.https.any.worker-expected.txt:
* LayoutTests/storage/filesystemaccess/resources/sync-access-handle-basics.js:
* LayoutTests/storage/filesystemaccess/resources/sync-access-handle-close.js:
(testFunction):
(testFunctions):
(async testMultipleHandles):
(async test):
(testSyncFunction): Deleted.
(async testAsyncFunction): Deleted.
(async testFunctions): Deleted.
* LayoutTests/storage/filesystemaccess/resources/sync-access-handle-read-write.js:
(async test):
* LayoutTests/storage/filesystemaccess/sync-access-handle-close-worker-expected.txt:
* LayoutTests/storage/filesystemaccess/sync-access-handle-read-write-worker-expected.txt:
* Source/WebCore/Modules/filesystemaccess/FileSystemFileHandle.cpp:
(WebCore::FileSystemFileHandle::createSyncAccessHandle):
(WebCore::FileSystemFileHandle::closeSyncAccessHandle):
* Source/WebCore/Modules/filesystemaccess/FileSystemFileHandle.h:
* Source/WebCore/Modules/filesystemaccess/FileSystemStorageConnection.h:
* Source/WebCore/Modules/filesystemaccess/FileSystemSyncAccessHandle.cpp:
(WebCore::FileSystemSyncAccessHandle::~FileSystemSyncAccessHandle):
(WebCore::FileSystemSyncAccessHandle::truncate):
(WebCore::FileSystemSyncAccessHandle::getSize):
(WebCore::FileSystemSyncAccessHandle::flush):
(WebCore::FileSystemSyncAccessHandle::close):
(WebCore::FileSystemSyncAccessHandle::closeInternal):
(WebCore::FileSystemSyncAccessHandle::read):
(WebCore::FileSystemSyncAccessHandle::write):
(WebCore::FileSystemSyncAccessHandle::stop):
(WebCore::FileSystemSyncAccessHandle::invalidate):
(WebCore::FileSystemSyncAccessHandle::isClosingOrClosed const): Deleted.
(WebCore::FileSystemSyncAccessHandle::closeFile): Deleted.
(WebCore::FileSystemSyncAccessHandle::didCloseFile): Deleted.
(WebCore::FileSystemSyncAccessHandle::closeBackend): Deleted.
(WebCore::FileSystemSyncAccessHandle::didCloseBackend): Deleted.
(WebCore::FileSystemSyncAccessHandle::completePromise): Deleted.
* Source/WebCore/Modules/filesystemaccess/FileSystemSyncAccessHandle.h:
* Source/WebCore/Modules/filesystemaccess/FileSystemSyncAccessHandle.idl:
* Source/WebCore/Modules/filesystemaccess/WorkerFileSystemStorageConnection.cpp:
(WebCore::WorkerFileSystemStorageConnection::closeSyncAccessHandle):
* Source/WebCore/Modules/filesystemaccess/WorkerFileSystemStorageConnection.h:
* Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp:
(WebKit::NetworkStorageManager::closeSyncAccessHandle):
* Source/WebKit/NetworkProcess/storage/NetworkStorageManager.h:
* Source/WebKit/NetworkProcess/storage/NetworkStorageManager.messages.in:
* Source/WebKit/WebProcess/WebCoreSupport/WebFileSystemStorageConnection.cpp:
(WebKit::WebFileSystemStorageConnection::closeSyncAccessHandle):
* Source/WebKit/WebProcess/WebCoreSupport/WebFileSystemStorageConnection.h:

Canonical link: https://commits.webkit.org/258473@main

f82b26e

Misc iOS, tvOS & watchOS macOS Linux Windows
βœ… πŸ§ͺ style βœ… πŸ›  ios βœ… πŸ›  mac βœ… πŸ›  wpe βœ… πŸ›  πŸ§ͺ win
βœ… πŸ§ͺ bindings βœ… πŸ›  ios-sim βœ… πŸ›  mac-AS-debug βœ… πŸ›  gtk βœ… πŸ›  wincairo
βœ… πŸ§ͺ webkitperl βœ… πŸ§ͺ ios-wk2 βœ… πŸ§ͺ api-mac βœ… πŸ§ͺ gtk-wk2
  πŸ§ͺ api-ios βœ… πŸ§ͺ mac-wk1   πŸ§ͺ api-gtk
βœ… πŸ›  tv βœ… πŸ§ͺ mac-wk2
βœ… πŸ›  tv-sim βœ… πŸ§ͺ mac-AS-debug-wk2
βœ… πŸ›  watch βœ… πŸ§ͺ mac-wk2-stress
βœ… πŸ›  πŸ§ͺ merge βœ… πŸ›  watch-sim

@szewai szewai requested a review from cdumez as a code owner December 21, 2022 20:24
@szewai szewai self-assigned this Dec 21, 2022
@szewai szewai added the New Bugs Unclassified bugs are placed in this component until the correct component can be determined. label Dec 21, 2022
@szewai szewai force-pushed the eng/Make-all-FileSystemSyncAccessHandle-methods-sync branch from c1b9d31 to 64ab51f Compare January 4, 2023 02:04
@szewai szewai requested a review from youennf January 4, 2023 07:06
Copy link
Contributor

@youennf youennf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.
Please check whether close should block until the job is done in network process.
Some other nits below.

FAIL SyncAccessHandle.write fails after SyncAccessHandle.close promise_test: Unhandled rejection with value: object "InvalidStateError: AccessHandle is closed"
FAIL SyncAccessHandle.flush fails after SyncAccessHandle.close promise_test: Unhandled rejection with value: object "InvalidStateError: AccessHandle is closed"
FAIL SyncAccessHandle.getSize fails after SyncAccessHandle.close promise_test: Unhandled rejection with value: object "InvalidStateError: AccessHandle is closed"
FAIL SyncAccessHandle.truncate fails after SyncAccessHandle.handle.close promise_test: Unhandled rejection with value: object "InvalidStateError: AccessHandle is closed"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we file a bug to fix these?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes; will file.

});
});
bool succeeded = FileSystem::truncateFile(m_file.handle(), size);
return succeeded ? ExceptionOr<void> { } : Exception { UnknownError };
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://fs.spec.whatwg.org/#api-filesystemsyncaccesshandle-truncate is using InvalidStateError, maybe we should use this one with a message.
This may apply to other methods.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good; will update.

if (isClosingOrClosed())
return promise.reject(Exception { InvalidStateError, "AccessHandle is closing or closed"_s });
if (m_isClosed)
return Exception { InvalidStateError, "AccessHandle is closed"_s };

auto* scope = downcast<WorkerGlobalScope>(scriptExecutionContext());
if (!scope)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pre-existing issue but we do not use scope, do we need the downcast and the if check (here and below)?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, we probably should remove it now that they are unused; will do.

for (auto& callback : callbacks)
callback(ExceptionOr<void> { *m_closeResult });
if (shouldNotifyBackend == ShouldNotifyBackend::Yes)
m_source->closeSyncAccessHandle(m_identifier);
}

ExceptionOr<unsigned long long> FileSystemSyncAccessHandle::read(BufferSource&& buffer, FileSystemSyncAccessHandle::FilesystemReadWriteOptions options)
{
ASSERT(!isMainThread());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can either add these asserts to the other methods or remove these asserts since all methods are doing IO now in the same thread.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure; will remove.


mainThreadConnection->closeSyncAccessHandle(identifier, accessHandleIdentifier, WTFMove(mainThreadCallback));
callOnMainThread([workerThread = Ref { m_scope->thread() }, mainThreadConnection = m_mainThreadConnection, identifier, accessHandleIdentifier]() mutable {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need workerThread?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No

void FileSystemSyncAccessHandle::didCloseFile()
{
closeBackend(CloseMode::Async);
closeInternal(ShouldNotifyBackend::Yes);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In case of ShouldNotifyBackend::Yes, should we block the worker thread until getting the notification from the backend?
If we do not block, could there be race conditions happening within the web app (say the web app has two workers doing IO?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you elaborate on the race condition case? A file can only have one FileSystemSyncAccessHandle at a time.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am thinking two web workers, the first one calls close and posts a message to the second one which immediately creates a sync handle on the same file entry.
A race condition between the close and the creation could theoretically happen although I am not sure this can happens today.
Say if the two web workers are in different processes and the postMessage does not go through the networking process.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, so the theoretical case is

  1. worker1 closes access handle, sends message "close access handle" to network process and sends message "start" to worker2
  2. worker2 receives the "start" message, and sends message "create access handle" to network process
  3. network process receives "create access handle" message from worker 1 before "close access handle" from worker, and will fail the "create access handle" message

Is it possible that two web processes can talk to each other without going through network process? (The SyncAccessHandle is only available in DedicatedWorker now)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the past postMessage was through UIProcess, now it is going through NetworkProcess, though it might be handled in a different thread than file sync.
WebLock is another possibility and is UIProcess based IIRC.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels like a rare case that network process will handle "create" message before the "close" message, as the "close access handle" message will be sent directly from web process 1 to network process, and the "create access handle" message from web process 2 will be sent after:

  1. UI process receives the "release lock" message from web process 1
  2. web process 2 receives "acquire lock" message from UI process

We could make the change if it turns out to be an issue I guess; blocking worker thread on close seems not too good for performance.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed this is rare, but this is the kind of issues that are very hard to diagnose.
Could you check what Chrome is doing here?

The spec is loose in the definition of close, it seems your interpretation might be correct since the only explicit step is to set the state. It might be worth having a more precise definition of close.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems Chrome waits until close message is replied; I will make the change to be compatible (https://bugs.webkit.org/show_bug.cgi?id=250194).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I filed whatwg/fs#83 to keep track of this on spec side.

@szewai szewai force-pushed the eng/Make-all-FileSystemSyncAccessHandle-methods-sync branch from 64ab51f to f82b26e Compare January 4, 2023 21:38
@szewai szewai added the merge-queue Applied to send a pull request to merge-queue label Jan 5, 2023
https://bugs.webkit.org/show_bug.cgi?id=247071
rdar://problem/101620396

Reviewed by Youenn Fablet.

To match latest spec: https://fs.spec.whatwg.org/#api-filesystemsyncaccesshandle. Chrome has already shipped it.

* LayoutTests/imported/w3c/web-platform-tests/fs/FileSystemSyncAccessHandle-close.https.tentative.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/fs/FileSystemSyncAccessHandle-flush.https.tentative.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/fs/FileSystemSyncAccessHandle-getSize.https.tentative.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/fs/FileSystemSyncAccessHandle-truncate.https.tentative.worker-expected.txt:
* LayoutTests/imported/w3c/web-platform-tests/fs/idlharness.https.any.worker-expected.txt:
* LayoutTests/storage/filesystemaccess/resources/sync-access-handle-basics.js:
* LayoutTests/storage/filesystemaccess/resources/sync-access-handle-close.js:
(testFunction):
(testFunctions):
(async testMultipleHandles):
(async test):
(testSyncFunction): Deleted.
(async testAsyncFunction): Deleted.
(async testFunctions): Deleted.
* LayoutTests/storage/filesystemaccess/resources/sync-access-handle-read-write.js:
(async test):
* LayoutTests/storage/filesystemaccess/sync-access-handle-close-worker-expected.txt:
* LayoutTests/storage/filesystemaccess/sync-access-handle-read-write-worker-expected.txt:
* Source/WebCore/Modules/filesystemaccess/FileSystemFileHandle.cpp:
(WebCore::FileSystemFileHandle::createSyncAccessHandle):
(WebCore::FileSystemFileHandle::closeSyncAccessHandle):
* Source/WebCore/Modules/filesystemaccess/FileSystemFileHandle.h:
* Source/WebCore/Modules/filesystemaccess/FileSystemStorageConnection.h:
* Source/WebCore/Modules/filesystemaccess/FileSystemSyncAccessHandle.cpp:
(WebCore::FileSystemSyncAccessHandle::~FileSystemSyncAccessHandle):
(WebCore::FileSystemSyncAccessHandle::truncate):
(WebCore::FileSystemSyncAccessHandle::getSize):
(WebCore::FileSystemSyncAccessHandle::flush):
(WebCore::FileSystemSyncAccessHandle::close):
(WebCore::FileSystemSyncAccessHandle::closeInternal):
(WebCore::FileSystemSyncAccessHandle::read):
(WebCore::FileSystemSyncAccessHandle::write):
(WebCore::FileSystemSyncAccessHandle::stop):
(WebCore::FileSystemSyncAccessHandle::invalidate):
(WebCore::FileSystemSyncAccessHandle::isClosingOrClosed const): Deleted.
(WebCore::FileSystemSyncAccessHandle::closeFile): Deleted.
(WebCore::FileSystemSyncAccessHandle::didCloseFile): Deleted.
(WebCore::FileSystemSyncAccessHandle::closeBackend): Deleted.
(WebCore::FileSystemSyncAccessHandle::didCloseBackend): Deleted.
(WebCore::FileSystemSyncAccessHandle::completePromise): Deleted.
* Source/WebCore/Modules/filesystemaccess/FileSystemSyncAccessHandle.h:
* Source/WebCore/Modules/filesystemaccess/FileSystemSyncAccessHandle.idl:
* Source/WebCore/Modules/filesystemaccess/WorkerFileSystemStorageConnection.cpp:
(WebCore::WorkerFileSystemStorageConnection::closeSyncAccessHandle):
* Source/WebCore/Modules/filesystemaccess/WorkerFileSystemStorageConnection.h:
* Source/WebKit/NetworkProcess/storage/NetworkStorageManager.cpp:
(WebKit::NetworkStorageManager::closeSyncAccessHandle):
* Source/WebKit/NetworkProcess/storage/NetworkStorageManager.h:
* Source/WebKit/NetworkProcess/storage/NetworkStorageManager.messages.in:
* Source/WebKit/WebProcess/WebCoreSupport/WebFileSystemStorageConnection.cpp:
(WebKit::WebFileSystemStorageConnection::closeSyncAccessHandle):
* Source/WebKit/WebProcess/WebCoreSupport/WebFileSystemStorageConnection.h:

Canonical link: https://commits.webkit.org/258473@main
@webkit-early-warning-system webkit-early-warning-system force-pushed the eng/Make-all-FileSystemSyncAccessHandle-methods-sync branch from f82b26e to acd30cd Compare January 5, 2023 05:10
@webkit-commit-queue
Copy link
Collaborator

Committed 258473@main (acd30cd): https://commits.webkit.org/258473@main

Reviewed commits have been landed. Closing PR #7972 and removing active labels.

@webkit-commit-queue webkit-commit-queue removed the merge-queue Applied to send a pull request to merge-queue label Jan 5, 2023
@webkit-early-warning-system webkit-early-warning-system merged commit acd30cd into WebKit:main Jan 5, 2023
@szewai szewai deleted the eng/Make-all-FileSystemSyncAccessHandle-methods-sync branch January 10, 2023 17:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
New Bugs Unclassified bugs are placed in this component until the correct component can be determined.
Projects
None yet
4 participants