2013-07-29 4 views
2

Nous développons une application Cocoa pour Mac OSX (10.8) qui a besoin d'utiliser une bibliothèque JavaScript (longue histoire pourquoi nous doit utiliser JavaScript). Dans une application de démonstration, tout semblait aller bien, mais tout en incorporant le code dans notre projet, nous pouvons appeler la fonction 37 fois sans problèmes, puis se bloque pour la 38ème fois.Cocoa/Mac: Crash JavaScript Core sur le 38e appel

Pour appeler le code JS, nous utilisons JSWrappers.m d'Apple (à partir de l'exemple JavaScriptCoreHeadStart). La ligne qui tombe en panne (avec un EXC_BAD_ACCESS) est # 149:

JSObjectCallAsFunction(self.jsContext, jsFunction, NULL, argumentCount, arguments, NULL); 

Comme indiqué plus haut, il se bloque sur la 38ème fois -callStringJSFunction:withParameters: est appelé, peu importe ce que l'entrée est (il se bloque avec une chaîne d'entrée, et la même chaîne fonctionne si elle est utilisée dans les 37 itérations précédentes). Le EXC_BAD_ACCESS n'est pas provoqué par une variable d'entrée, en tant qu'accès (comme l'appel self.jsContext juste avant cette ligne) fonctionne: c'est l'appel de fonction lui-même qui provoque le plantage.

Nous n'avons aucune idée de ce qui peut causer ce problème, et aucune idée sur la façon de déboguer plus. Quelqu'un at-il un indice? Merci.

// EDIT

Je dois me corriger: il ne fonctionne pas sur la "démo app" aussi. Même dans ce cas, le code tombe en panne la 38ème fois que nous appelons -callStringJSFunction:withParameters:

// EDIT2

Si nous Recréez le JSWrappers objet (et un nouveau JSGlobalContext) chaque fois que la fonction est appelée, elle ne tombe pas en panne plus. Cependant, cela rend le code beaucoup plus lent (ce qui n'est pas surprenant, car l'interpréteur JS doit lire le script à chaque fois - et c'est un assez gros).

// EDIT3

Une autre découverte: la construction de l'application en 32 bits fait le crash de code. Construire en 64 bits, à la place, fonctionne parfaitement: le code JS est exécuté sans problèmes à tout moment que nous souhaitons. C'est étrange: cela pourrait-il être un bug dans le framework JavaScript Core lui-même?

Répondre

1

Répondre à ma propre question.

Apparemment, c'est un bug (?) Dans JavaScript Core. Sur les binaires 32 bits, pour certaines raisons, nous ne pouvons pas appeler la fonction plus de 37 fois (problèmes de mémoire?). Ces problèmes n'apparaissent pas sur les binaires 64 bits.

Ce problème se produit sur OSX 10.8.4.

+0

Je rencontre quelque chose de similaire. Avez-vous un radar que je peux reproduire? – Simon

+0

@ Simon Je suis désolé, je ne sais pas. Cependant, je suis sûr que c'est un bug avec JavaScript Core, probablement lié à la mémoire (ma bibliothèque JS était assez grande). – Qualcuno

0

Un peu d'un ancien fil, mais quelque peu pertinent aujourd'hui.
Nous prenons toujours en charge le retour à iOS 8.2 et avons constaté que ce problème se produisait avec un certain nombre d'utilisateurs iOS 8.4. Certaines recherches montrent que cela semble être un bug avec les versions iOS à cette époque. Sous les tests de synthèse, j'appelais la même fonction -callWithArguments:@[] sur plusieurs threads (un nouveau thread dans une boucle forcée de 100 count) - cela compléterait sur la plupart des appareils de test, même l'iPod touch 32 bits, fonctionnant sous iOS 9.x . Le dénominateur commun était iOS 8.x, même sur l'iPhone 5S (64bit, 1Go de RAM), provoquant un WTFCrash.

Dans notre application de production, l'application appelle le callWithArguments asynchrone et, à l'occasion, simultanément sur plusieurs threads. Il semble que plusieurs threads appelaient une fonction de longue durée en même temps et causaient des problèmes. Pour arrêter puis, j'Enveloppez la callWithArguments dans un

@synchronized (<#token#>) { 
     <#statements#> 
    } 

Cela semblait gérer cela et arrêté sur les accidents toutes les versions iOS testées (8.4, 9.x, 10.3) et de multiples architectures. Comme ces appels étaient effectués sur des threads de fond, cela n'avait aucun impact sur l'interface utilisateur. Bien que ce ne soit pas l'approche/résolution la plus gracieuse, il semble que nous ayons résolu notre problème lorsque des dizaines d'utilisateurs recevaient des plantages intermittents chaque jour. Cela dit, si quelqu'un connaît une meilleure façon de le faire, s'il vous plaît faites le moi savoir.

tl; dr
Plusieurs threads appelant la même fonction causé à la bombe avec WTFCrash. Envelopper l'appel dans un verrou @synchronized a semblé le réparer.