NativeScript / NativeScript/ios

isImplementedInClass leaks the losing sample instance on re-entrant or racing cache population

Ouverte
#459 1 commentaire 0 réactions 0 personnes assignées Voir sur GitHub

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:

  1. [klass alloc] runs outside the mutex — deliberately, because alloc can trigger +initialize, which may run arbitrary code that re-enters this method (holding the lock would deadlock).
  2. 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 never init'd, so -release runs -dealloc against 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 -dealloc that does CFRelease/dispatch_release on a zero ivar traps, and UIKit teardown off the main thread is asserting territory.
  • Holding the lock across alloc deadlocks via the +initialize re-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

  1. Lisez l'issue en entier, puis le guide de contribution du projet.
  2. Signalez en commentaire que vous la prenez — cela évite que deux personnes fassent le même travail.
  3. Forkez le dépôt et travaillez sur une branche.
  4. 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

Recevez les nouvelles issues par e-mail

Un résumé court des issues GitHub adaptées aux débutants.