antlr / stringtemplate4

StringTemplate 4
http://www.stringtemplate.org
Other
955 stars 231 forks source link

STGroupFile.load is not synchronized #203

Closed bobflannigon closed 6 years ago

bobflannigon commented 6 years ago

In a multi-threaded environment it's possible to attempt to load a template in two separate threads.

To reproduce: Requires two concurrent calls to STGroup.getInstanceOf("foo") on a previously unloaded template file. Only achiveable in a debug environment. Thread 1: Calls STGroup.getInstance("foo") Thread 1: Starts STGroupFile.load, marks 'alreadyLoaded' as true Thread 1: Suspend thread before entering STGroupFile.loadGroupFile (it's easiest to reproduce if the template hasn't done any template loading). Thread 2: Calls STGroup.getInstance("foo") [it doesn't have to be 'foo', just one that isn't loaded] Thread 2: Calls STGroupFile.load but returns as 'alreadyLoaded' is true Thread 2: Call to getInstance("blah") returns null because template is marked as loaded but isn't actually loaded. Thread 2: Explodes (NullPointerException etc.) Thread 1: Completes loading of template, returns it successfully and carries on happily.

Expected Behaviour STGroupFile.unload is a synchronized method, yet load is not? STGroupFile.load must be at least partially synchronized so the loading of the file and the setting of 'alreadyLoaded' are atomic such that subsequent threads wait to read alreadyLoaded if loading is in-progress (i.e. using a lock object). I imagine it's possible to call STGoupFile.unload whilst STGroupFile.load is in progress and actually complete unloading before load even begins (simply using the steps above), therefore after both threads are complete, the template is actually loaded!

Workaround: Synchronize calls to getInstance("blah") in local code.

parrt commented 6 years ago

The idea we had originally was for separate threads to create their own template group objects; nonetheless, I merged something that should solve this particular problem:

https://github.com/antlr/stringtemplate4/pull/195