2015-12-09 3 views
1

Je crée une extension native pour un nœud qui inclut une opération de longue durée avec un rappel à la fin.Nœud NAN: obtention d'une erreur d'appel appelant GetFromPersistent dans la méthode Execute d'AsyncWorker

Je passe un tampon de noeud à l'appel. Il contient la charge utile de ce qui doit être traité par l'extension.

Je devrais pouvoir stocker mon tampon dans le stockage persistant dans le constructeur de mon AsyncWorker, et le récupérer plus tard quand j'en ai besoin.

Cet exemple (de la suite de test nan) est ce que je fonde généralement mon code sur: https://github.com/nodejs/nan/blob/master/test/cpp/bufferworkerpersistent.cpp

Ce test fonctionne, mais il ne fait rien avec le tampon jusqu'à ce que la méthode HandleOKCallback, qui ISN Pas super intéressant pour moi. J'ai besoin d'accéder au tampon pendant la méthode Execute.

Si je simplement ajouter une ligne à la méthode Execute() du test pour tenter d'accéder à la mémoire tampon, comme celui-ci:

void Execute() { 
    printf("before GetFromPersistent\n"); 
    v8::Local<v8::Value> handle = GetFromPersistent("buffer"); 
    printf("after GetFromPersistent\n"); 
    printf("buffer @%llux len %ld\n", (uint64_t)node::Buffer::Data(handle), node::Buffer::Length(handle)); 
    Sleep(milliseconds); 
} 

Je reçois une erreur de seg sur l'appel GetFromPersistent.

Ma question est: qu'est-ce qui me manque? Devrais-je ne pas être en mesure de tirer un objet persistant dans la méthode Execute? Si oui, pourquoi pas?

Répondre

2

OK, je pense que la réponse est « duh », mais pour d'autres débutez avec des extensions natives Node, voici ce que je comprends maintenant se passe:

Depuis le noeud est un seul thread, les tâches de longue durée doit s'exécuter dans un thread différent s'ils ne doivent pas bloquer le noeud.

Nan utilise libuv pour gérer un pool de threads pour effectuer le travail asynchrone que vous écrivez dans la méthode "Execute". Cependant, le constructeur de votre AsyncWorker s'exécute réellement sur le thread du noeud, et le HandleOKCallback est également programmé pour s'exécuter une fois que Execute est terminé. Il est donc possible d'accéder aux ressources des nœuds dans le constructeur et dans la configuration du rappel, mais comme Exécuter s'exécute sur un thread différent, ce n'est pas OK, donc il segmente les erreurs. Donc, pour mon problème (je cours un décodage JPEG dans un AsyncWorker), je tire plutôt le pointeur et la longueur hors du tampon dans le constructeur, mais j'appelle toujours SaveToPersistent sur le buffer pour qu'il ne soit pas GCed pendant que je décrypte les bits.