NativeScript / NativeScript/ios
isImplementedInClass leaks the losing sample instance on re-entrant or racing cache population
Personne n'a encore pris cette issue.
- Langage dominant
- JavaScript
- Étoiles
- 150
- Forks
- 43
- Merge moyen
- 3 j 10 h
- PR mergées (30 j)
- 22
Description
Problem
MethodMeta::isImplementedInClass (NativeScript/runtime/Metadata.mm) keeps a process-wide cache of [klass alloc]-created sample instances used to answer respondsToSelector: for classes whose alloc returns a different class or which forward messages. The cache is populated like this:
[klass alloc]runs outside the mutex — deliberately, becausealloccan trigger+initialize, which may run arbitrary code that re-enters this method (holding the lock would deadlock).- The lock is then taken and
sampleInstances.emplace(klass, instance)inserts.
When the emplace loses — the re-entrant call already populated the entry for the same class, or another thread raced — the freshly allocated instance is abandoned: one leaked object per lost race (Instruments shows these as e.g. a leaked UIAlertView / NSURLSessionConfiguration attributed to isImplementedInClass). The count varies run to run since it is timing-dependent.
Why the obvious fixes don't work
- Releasing the loser is unsafe: the instance is
alloc'd but neverinit'd, so-releaseruns-deallocagainst zero-filled ivars of an arbitrary framework class, on whatever thread the probe ran on (it demonstrably runs on worker threads). Benign for most classes, but a-deallocthat doesCFRelease/dispatch_releaseon a zero ivar traps, and UIKit teardown off the main thread is asserting territory. - Holding the lock across
allocdeadlocks via the+initializere-entry described above. - Parking losers in a static container merely converts the unreachable leak into intentional perpetual retention — it silences Instruments without reclaiming anything (tried and reverted in #458).
Potential solutions
- A re-entrancy-aware locking scheme (recursive mutex, or a reader/writer arrangement) so the populate path can be made atomic with respect to re-entrant probes without deadlocking through
+initialize. - Reuse already-
alloc-ed objects: when a sample for that Class is requested (or something else calls[thatClass alloc]through the runtime), hand out / consume the cached instance instead of allocating another, so a losing instance gets used rather than abandoned.
The leak site carries a comment pointing at this issue.
Guide de contribution
Ouvrir le guide de contribution
Par où commencer
- Lisez l'issue en entier, puis le guide de contribution du projet.
- Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
- Forkez le dépôt et travaillez sur une branche.
- Ouvrez une pull request qui référence le numéro de l'issue.
Piste de recherche
Commencez dans NativeScript/runtime/Metadata.mm, au niveau de MethodMeta::isImplementedInClass et du commentaire qui renvoie à cette issue ; suivez le remplissage de sampleInstances, l’utilisation du mutex et le comportement re-entrant de alloc. Le travail est considéré comme terminé lorsque les sample instances abandonnées pendant un remplissage re-entrant ou concurrent sont éliminées, sans provoquer de deadlock, de libération non sûre ni de rétention perpétuelle intentionnelle.
Rédigé par le modèle d'indexation à partir du texte de l'issue.
Évaluation
- Stack technique
- cpp, objective-c
- Domaine
- mobile-dev
- Type d'issue
- Bug
- Difficulté
- 5/5
- Temps estimé
- Plus d'une semaine
- Activité
- Active
- Clarté
- Plutôt claire
- Accessibilité débutants
- 38/100