[
WFCORE-2235] Fixing race condition that appears when the following scenario happens:
Module A depends on module B (optional dependency).
Both modules are dynamic (they're not present on the file system
but dynamically deployed at runtime). The following scenario exposes
race condition for this kind of dynamic modules:
1] Module A is starting and module B is not available yet
2] Module A during its initialization phase calls
ModuleLoader.loadModuleLocal() to resolve its optional module B dependency
3] Module A initialization thread registers "newFuture" with "moduleMap"
4] Module A initialization thread fails to find ModuleSpec of module B
5] ModuleLoadService representing Module B appears and is starting
(such service knows all its preconditions are met - its ModuleSpec is available)
6] MSC thread executing ModuleLoadService.start() (of module B)
is calling moduleLoader.loadModule(moduleB_Id)
7] MSC thread executing ModuleLoadService.start() (of module B)
enters ModuleLoader.loadModuleLocal() to find the module
8] MSC thread requests "moduleMap" and receives "newFuture" created in step [3]
9] MSC thread enters "newFuture" wait set and blocks (waiting for Module A
initialization thread to complete)
10] Module A initialization thread wakes up and identifies that (moduleSpec == null)
MOduleLoader.loadModuleLocal() will return null
11] Before method return "finally" sections is executed, where:
a) newFuture.setModule(null) is called
b) "newFuture" is removed from "moduleMap"
12] MSC thread wakes up and throws ModuleNotFoundException
This fix ensures proper ordering of resolution process for dynamic modules
and fixes aforementioned race condition.