Kan lokale opslag worden gefingeerd/gehackt?

Ik vind mezelf een beetje een quandry.

Ik heb een grote applicatie die Google's V8 JavaScript engine heeft. Sommige oproepen worden gedaan naar de V8-engine op de UI-thread. Om aardig te zijn voor de gebruiker zoals iedereen aanbeveelt, worden sommige lange bewerkingen op een afzonderlijke thread uitgevoerd, zonder de UI-thread te hangen. Deze langlopende bewerkingen doen echter ook een beroep op de V8-javascript-engine. Dus meerdere threads bellen naar V8.

Ding is, lijkt V8 thread lokale opslag te gebruiken. Dit lijkt mijn applicatie willekeurig te laten ontploffen. Het zit zeker in de klas van "Hoe was dit mogelijk tot nu toe aan het werken?" bugs.

Zonder mijn aanvraag significant te herontwerpen, stel ik een lelijke, lelijke vreselijke super-hack voor: kan ik V8 laten denken dat het op een andere draad werkt?

Met andere woorden, de eerste keer dat ik naar V8 telefoneer, noteer ik de thread. Vervolgens, voor alle andere oproepen naar V8 , spoof ik op de een of andere manier de thread zodat de lokale thread-opslag/wat dan ook thread-dependent werkt.

Kan het worden gedaan? Zal het werken? Ben ik stom om een ​​dergelijke scummy-hack eens in overweging te nemen?

4
Waarom zou thread-local storage je toepassing willekeurig laten crashen? Wetende dat kan helpen het probleem op te lossen zonder hacks.
toegevoegd de auteur R. Martinho Fernandes, de bron
Voordat je het probleem probeert op te lossen, moet je het duidelijk diagnosticeren.
toegevoegd de auteur David Heffernan, de bron
Wat voor soort oproepen naar V8? Als V8 niet goed overweg kan met meerdere threads, hoeft u alleen maar eenvoudig gediagnosticeerde bugs uit te wisselen voor subtielere, onvoorspelbare en moeilijk te debuggen fouten. Je moet echt kijken, ik kijk naar manieren om je V8-gesprekken in serie te zetten
toegevoegd de auteur jalf, de bron

2 antwoord

Je zou niks moeten vervalsen. In plaats daarvan zou je V8 moeten vertellen dat je het vanuit de andere thread probeert te gebruiken.

In V8 prior to the version 3.2 the only way to do that is to use v8::Locker before using V8 from the different thread. It guarantees both exclusive access to the V8 and initializes internal structures stored in TLS. For more details see http://code.google.com/p/v8/source/browse/branches/3.1/include/v8.h#3189

Starting from the version 3.2 V8 has the concept of isolate. If you are not creating isolates explicitly, V8 implicitly creates the default isolate to keep API compatible. In this case you can still simply use v8::Locker as in older versions. If you are creating isolates explicitly then in addition to acquiring exclusive access with v8::Locker you also have to enter&exit them explicitly in your threads using v8::Isolate::Enter/v8::Isolate::Exit methods or v8::Isolate::Scope. For more details see http://code.google.com/p/v8/source/browse/trunk/include/v8.h#3510

Een eenvoudig antwoord dat in de meeste gevallen zal werken is: gebruik v8 :: Locker voordat u V8 uit de verschillende threads gebruikt.

19
toegevoegd
Bedankt, dat is een veel betere oplossing. Ik was ver weg!
toegevoegd de auteur AshleysBrain, de bron

Ik had hetzelfde probleem en kon de oplossing gedeeltelijk vinden via deze thread. Om het antwoord van VE uit te werken, kun je standaard geen v8 uit meerdere threads gebruiken. Als je wilt, moet je isolaten en sloten gebruiken.

Het probleem is dat je niet halverwege kunt gaan, je kunt alleen sloten gebruiken tenzij je je JS-context volledig verlaat en vernietigt. Omdat dit niet het geval is in de meeste niet-triviale gevallen, moet je helemaal doorgaan, en

  1. Maak uw eigen v8 :: Isolate . Je kunt dit globaal maken, maar (zoals ik het begrijp) kan het niet de standaard zijn (omdat de standaard al in de ingevoerde staat is).

  2. In al uw functies die v8 aanroepen (en die niet gegarandeerd intern zijn), moet u uw isolaat invoeren (gebruik v8 :: Isolate :: Scope ) en

  3. gebruikt ook 'v8 :: Locker'-objecten.

Ik schreef een klein helper-object dat ik gebruik in mijn openbare methoden en het ziet er ongeveer zo uit:

class SessionLock {
private:
    v8::Isolate::Scope scope;
    v8::Locker lock;

public:
    SessionLock() : scope(getSessionIsolate()), lock(getSessionIsolate()) {}
};
1
toegevoegd