Fix editor exit hang when GutenbergView never finishes loading#22882
Open
jkmassel wants to merge 1 commit into
Open
Fix editor exit hang when GutenbergView never finishes loading#22882jkmassel wants to merge 1 commit into
jkmassel wants to merge 1 commit into
Conversation
Collaborator
Contributor
|
|
Contributor
|
|
fac8211 to
785ecd8
Compare
Contributor
🤖 Build Failure AnalysisThis build has failures. Claude has analyzed them - check the build annotations for details. |
Track ready state from `setEditorDidBecomeAvailable` and short-circuit the save-on-exit flow to `UpdateFromEditor.Failed` when the editor isn't ready. Bound the bridge latch with a 5s timeout that also routes through `Failed`. Both paths skip mutating the `PostModel`, so the user's existing draft is preserved when the editor stalls. Fixes #22878
785ecd8 to
8e8b670
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.


Summary
If
GutenbergViewnever finishes loading (e.g. an upstream 404 onwp-block-editor/v1/settings, network failure mid-init, or any other case where the JS bridge never becomes available), the editor activity gets stuck — back press doesn't dismiss it, the "saving" progress dialog stays open, and the only way out is to force-stop the app.Fixes #22878.
Root cause
GutenbergKitEditorFragment.getTitleAndContentblocks onCountDownLatch.await()with no timeout. The save-on-exit flow (savePostAndOptionallyFinish→updateAndSavePostAsyncOnEditorExit→updateAndSavePostAsync→updateFromEditor→getTitleAndContent) sits on this latch waiting forTitleAndContentCallback.onResultto fire from JS. WhenGutenbergViewhasn't finished loading, the bridge call is dropped silently — GBKit internally guards on its privateisEditorLoadedfield and logs"You can't change the editor content until it has loaded".latch.countDown()never fires; the activity never finishes.Introduced incidentally by #22764 ("Upgrade GutenbergKit from v0.11.1 to v0.15.2"), which switched the bridge call from sync to async-with-latch.
Fix
GBKit doesn't currently expose a public ready-state property — only the
setEditorDidBecomeAvailable {}callback. Three layers, all host-side.1. Track ready state in the fragment
@Volatile var editorReadyflipped inside thesetEditorDidBecomeAvailable {}listener we already register; reset tofalseinonCreateViewso a staletruedoesn't leak across config changes.@Volatileis required because the field is written from the JS bridge thread and read frombgDispatcher(viaEditPostRepository.updateAsync). Exposed publicly viaisEditorReady().2. Bound the latch
Replace
latch.await()withlatch.await(5, TimeUnit.SECONDS). On timeout (orInterruptedException),getTitleAndContentthrowsEditorFragmentNotAddedExceptionrather than returning a sentinel emptyPair.3. Short-circuit the save flow before it mutates the
PostModelGutenbergKitActivity.updateFromEditorchecksisEditorReady()before callinggetTitleAndContent. When false (or when the timeout path throws), it returnsUpdateFromEditor.Failed(...).StorePostViewModel.updatePostObjectWithUItreatsFailedas a no-op —updatePostContentNewEditoris never called, the in-memoryPostModelis not mutated,_postChangeddoes not fire, and the auto-save observer atGutenbergKitActivity.kt:1158-1162does not run.This last step is load-bearing. An earlier draft of this PR returned
Pair("", "")fromgetTitleAndContenton stall, on the assumption that "empty post → no save attempted." That assumption was wrong._postChangedfires whenever the in-memoryPostModelchanges, andeditPostRepository.postChanged.observecallsstorePostViewModel.savePostToDbregardless ofshouldSavePost(). For an existing draft, the in-memory overwrite to empty would have been persisted to SQLite, silently wiping the user's content.Incidental: exception-class mismatch in
updateFromEditor's catchThe pre-existing catch was
catch (e: EditorFragmentAbstract.EditorFragmentNotAddedException), butGutenbergKitEditorFragmentthrowsGutenbergKitEditorFragmentBase.EditorFragmentNotAddedException— two unrelated inner classes sharing the same simple name, descending separately fromException. The catch was dead code. Changed to match the actually-thrown class so the new timeout-throw is caught.Net behaviour
Editor stall →
Failedreturned → noPostModelmutation → no DB write → activity finishes viaActivityFinishState.CANCELLEDwithin ~5s. Existing draft on disk is preserved.The underlying 404 / route-detection asymmetry on Atomic sites is a separate concern, owned by #22812 / capability-detection territory. This PR is specifically about the host's failure mode when the editor doesn't load, regardless of why it didn't load.
Test plan
automatticwidgets.wpcomstaging.com), the editor stalls with Theme Styles and Third-Party Blocks enabled (you'll need to turn these on in Site Settings to see it), open a post in the editor, wait for the stall, press the back button or X — the activity finishes within ~5 seconds instead of hanging indefinitely.savePostToDbcall is made when exiting from a stalled session (verify in logs).Related