How Quark iOS Cut JSC Crashes by Fixing Memory Leaks and AppWorker Bugs
This article details Quark iOS's systematic stability effort in 2022, describing how the team identified top JavaScriptCore crashes, traced them to memory‑leak and AppWorker issues, applied targeted feature toggles, upgraded SDKs, and ultimately achieved a sharp drop in overall crash rates.
Background
In mid‑March 2022, the release of iOS 15.4 caused a rapid increase in crash rates for the Quark iOS client, severely affecting user experience. After a long period without focused stability work, many historic issues had accumulated. The Quark iOS team therefore launched a stability‑governance effort, cleaning new problems while tackling long‑standing top‑crash items.
Overall Stability Governance Approach
Target top stability problems for focused attacks.
Enrich and improve existing stability infrastructure.
Add more effective monitoring to prevent regression.
Refine crash‑metric composition and clarify boundaries.
The most impactful work was addressing the top‑ranked crashes, especially those introduced by iOS 15.4, and the JSC‑related crashes described below.
Case Analysis
The crashes appeared in Quark Browser version 5.4.*, occupying three of the Top 10 crash slots and showing clear system‑version clustering.
Initial Mitigation
1.1 Locating the Issue via Crash Logs
Using the crash SDK, the team observed three common features: the three crashes occurred together, they clustered by iOS version, and the final crash message was identical – WTFCrashWithInfo(int, char const*, char const*, int). This indicated a single series of problems caused by differing JavaScriptCore versions across iOS releases.
1.2 Analyzing the JSC Crash Stack
The stack suggested two possible causes: excessive threads or memory pressure. Thread counts (50‑80) were far below risk thresholds, so memory pressure was investigated.
Crash‑SDK collected custom information, showing an average usable memory size of about 107 MB – not extremely low. Some users had ≤60 MB, while others were within safe limits.
Two rounds of memory investigation were performed using Instrument Memory Leak, an internal debugging tool, and Xcode’s Memory Graph. Overall memory‑crash trends improved, but JSC crashes remained unchanged.
Effective crash: captured by crash SDK (the case studied here). No‑log crash: not captured, only pre‑crash user behavior is available.
1.3 Identifying the Introduced Module
The upgrade of AppWorker – a JSI‑based background worker – was identified as the most likely trigger. Three potential layers were examined:
Business layer (specific JS code).
Core ability layer (high‑frequency event communication).
JSI layer (new features or interfaces).
Small‑scale AB tests showed that disabling AppWorker‑related modules slightly reduced crashes, disabling communication further reduced them, and fully disabling AppWorker eliminated the crashes. Because AppWorker is critical for many features, a compromise was made: it was disabled for low‑end devices that contributed disproportionately to crashes.
Deep Dive into Abnormal Information
Stability infrastructure was enhanced by integrating MetricKit, upgrading the crash SDK from PLCrash to KSCrash, and adding richer data capture. In August, VMMap support was added, allowing developers to view detailed memory usage at crash time.
2.1 Problem Localization
After VMMap integration, JSC crashes showed unusually high stack memory usage, whereas normal crashes had minimal stack memory. Analysis also revealed that a novel site (xs635.com) had surged to the top of crash URLs, unlike previous internal search sites.
Reproducing the scenario by repeatedly copying content on that site caused a stack‑memory leak that never released.
Symbol tracing pointed to a security component SDK. Relevant symbols:
__FCZLb7vLCQLWhr<br/>-[__NSSingleObjectSetI enumerateObjectsWithOptions:usingBlock:]<br/>__FCyaaEyd5fwkLRDebugging showed the leak was triggered by UIPasteboard notifications and system foreground/background switches.
2.2 Validation and Solution
Local debugging confirmed that massive clipboard‑copy operations on low‑end devices caused crashes. An online experiment disabled clipboard operations on the offending site by injecting the following JavaScript overrides:
navigator.clipboard.write = function(){};<br/>navigator.clipboard.writeText = function(strnum){};<br/>document.execCommandCopy = document.execCommand;<br/>document.execCommand = function(commandparam){<br/> if (commandparam == "copy") {} else { document.execCommandCopy(commandparam); }<br/>};After deployment, the site no longer appeared in crash reports.
Finally, the outdated security component SDK (version 6.5.11, two years old) was upgraded to the latest release, eliminating the memory‑leak issue entirely.
Analysis and Reflection
The JSC crashes were ultimately caused by a stack‑memory leak, and fixing the leak also reduced other memory‑related crashes. Effective crashes dropped, and overall memory‑crash incidence improved.
Effect Showcase
Following the mid‑August release of the fix, the overall crash rate fell sharply and continued a gradual decline.
Summary and Outlook
Quark iOS’s stability has markedly improved through continuous infrastructure upgrades and targeted case work such as the JSC crash remediation. The experience highlights the importance of proactive memory monitoring, turning accidental discoveries into systematic safeguards, and building dynamic memory‑monitoring capabilities to catch both stack and heap issues before they affect users.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
