Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Occasional concurrent modification issues with FastJ Scene System #86

Closed
1 task done
lucasstarsz opened this issue Aug 9, 2021 · 0 comments · Fixed by #117
Closed
1 task done

[Bug]: Occasional concurrent modification issues with FastJ Scene System #86

lucasstarsz opened this issue Aug 9, 2021 · 0 comments · Fixed by #117
Assignees
Labels
bug Something isn't working

Comments

@lucasstarsz
Copy link
Member

What happened?

While running FastJ unit tests, I received a ConcurrentModificationException from FastJ's scene system. It seems despite many efforts FastJ still has occasional threading issues.

How to Reproduce the Error

1. Run any FastJ program that uses the scene system.
2. (Very) occasionally, the error will appear.

FastJ Version

1.5.0 (Latest Version)

Java Version

Java 11

Relevant Exceptions/Log Output

Unexpected exception type thrown ==> expected: <java.lang.IllegalStateException> but was: <java.util.ConcurrentModificationException>
Expected :java.lang.IllegalStateException
Actual   :java.util.ConcurrentModificationException
<Click to see difference>

org.opentest4j.AssertionFailedError: Unexpected exception type thrown ==> expected: <java.lang.IllegalStateException> but was: <java.util.ConcurrentModificationException>
	at [email protected]/org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:65)
	at [email protected]/org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:37)
	at [email protected]/org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:3007)
	at fastj.library.test/unittest.testcases.systems.control.SceneManagerTests.trySceneManagerSetCurrentScene_bySceneName_withSceneNameThatDoesNotExist(SceneManagerTests.java:146)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at [email protected]/org.junit.platform.commons.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:688)
	at [email protected]/org.junit.jupiter.engine.execution.MethodInvocation.proceed(MethodInvocation.java:60)
	at [email protected]/org.junit.jupiter.engine.execution.InvocationInterceptorChain$ValidatingInvocation.proceed(InvocationInterceptorChain.java:131)
	at [email protected]/org.junit.jupiter.engine.extension.TimeoutExtension.intercept(TimeoutExtension.java:149)
	at [email protected]/org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestableMethod(TimeoutExtension.java:140)
	at [email protected]/org.junit.jupiter.engine.extension.TimeoutExtension.interceptTestMethod(TimeoutExtension.java:84)
	at [email protected]/org.junit.jupiter.engine.execution.ExecutableInvoker$ReflectiveInterceptorCall.lambda$ofVoidMethod$0(ExecutableInvoker.java:115)
	at [email protected]/org.junit.jupiter.engine.execution.ExecutableInvoker.lambda$invoke$0(ExecutableInvoker.java:105)
	at [email protected]/org.junit.jupiter.engine.execution.InvocationInterceptorChain$InterceptedInvocation.proceed(InvocationInterceptorChain.java:106)
	at [email protected]/org.junit.jupiter.engine.execution.InvocationInterceptorChain.proceed(InvocationInterceptorChain.java:64)
	at [email protected]/org.junit.jupiter.engine.execution.InvocationInterceptorChain.chainAndInvoke(InvocationInterceptorChain.java:45)
	at [email protected]/org.junit.jupiter.engine.execution.InvocationInterceptorChain.invoke(InvocationInterceptorChain.java:37)
	at [email protected]/org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:104)
	at [email protected]/org.junit.jupiter.engine.execution.ExecutableInvoker.invoke(ExecutableInvoker.java:98)
	at [email protected]/org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.lambda$invokeTestMethod$6(TestMethodTestDescriptor.java:210)
	at [email protected]/org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at [email protected]/org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.invokeTestMethod(TestMethodTestDescriptor.java:206)
	at [email protected]/org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:131)
	at [email protected]/org.junit.jupiter.engine.descriptor.TestMethodTestDescriptor.execute(TestMethodTestDescriptor.java:65)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:139)
	at [email protected]/org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
	at [email protected]/org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at [email protected]/org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at [email protected]/org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
	at [email protected]/org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
	at [email protected]/org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at [email protected]/org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	at java.base/java.util.ArrayList.forEach(ArrayList.java:1541)
	at [email protected]/org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.invokeAll(SameThreadHierarchicalTestExecutorService.java:38)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$5(NodeTestTask.java:143)
	at [email protected]/org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$7(NodeTestTask.java:129)
	at [email protected]/org.junit.platform.engine.support.hierarchical.Node.around(Node.java:137)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.lambda$executeRecursively$8(NodeTestTask.java:127)
	at [email protected]/org.junit.platform.engine.support.hierarchical.ThrowableCollector.execute(ThrowableCollector.java:73)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.executeRecursively(NodeTestTask.java:126)
	at [email protected]/org.junit.platform.engine.support.hierarchical.NodeTestTask.execute(NodeTestTask.java:84)
	at [email protected]/org.junit.platform.engine.support.hierarchical.SameThreadHierarchicalTestExecutorService.submit(SameThreadHierarchicalTestExecutorService.java:32)
	at [email protected]/org.junit.platform.engine.support.hierarchical.HierarchicalTestExecutor.execute(HierarchicalTestExecutor.java:57)
	at [email protected]/org.junit.platform.engine.support.hierarchical.HierarchicalTestEngine.execute(HierarchicalTestEngine.java:51)
	at [email protected]/org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:108)
	at [email protected]/org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:88)
	at [email protected]/org.junit.platform.launcher.core.EngineExecutionOrchestrator.lambda$execute$0(EngineExecutionOrchestrator.java:54)
	at [email protected]/org.junit.platform.launcher.core.EngineExecutionOrchestrator.withInterceptedStreams(EngineExecutionOrchestrator.java:67)
	at [email protected]/org.junit.platform.launcher.core.EngineExecutionOrchestrator.execute(EngineExecutionOrchestrator.java:52)
	at [email protected]/org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:96)
	at [email protected]/org.junit.platform.launcher.core.DefaultLauncher.execute(DefaultLauncher.java:75)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.processAllTestClasses(JUnitPlatformTestClassProcessor.java:99)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor$CollectAllTestClassesExecutor.access$000(JUnitPlatformTestClassProcessor.java:79)
	at org.gradle.api.internal.tasks.testing.junitplatform.JUnitPlatformTestClassProcessor.stop(JUnitPlatformTestClassProcessor.java:75)
	at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.stop(SuiteTestClassProcessor.java:61)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
	at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
	at com.sun.proxy.$Proxy5.stop(Unknown Source)
	at org.gradle.api.internal.tasks.testing.worker.TestWorker.stop(TestWorker.java:135)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:566)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
	at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:182)
	at org.gradle.internal.remote.internal.hub.MessageHubBackedObjectConnection$DispatchWrapper.dispatch(MessageHubBackedObjectConnection.java:164)
	at org.gradle.internal.remote.internal.hub.MessageHub$Handler.run(MessageHub.java:414)
	at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64)
	at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56)
	at java.base/java.lang.Thread.run(Thread.java:834)
Caused by: java.util.ConcurrentModificationException
	at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
	at java.base/java.util.HashMap$ValueIterator.next(HashMap.java:1521)
	at fastj.library/tech.fastj.systems.behaviors.BehaviorManager.reset(BehaviorManager.java:111)
	at fastj.library/tech.fastj.engine.FastJEngine.exit(FastJEngine.java:557)
	at fastj.library/tech.fastj.engine.FastJEngine.forceCloseGame(FastJEngine.java:401)
	at fastj.library/tech.fastj.engine.FastJEngine.error(FastJEngine.java:432)
	at fastj.library/tech.fastj.systems.control.SceneManager.sceneExistenceCheck(SceneManager.java:360)
	at fastj.library/tech.fastj.systems.control.SceneManager.setCurrentScene(SceneManager.java:100)
	at fastj.library.test/unittest.testcases.systems.control.SceneManagerTests.lambda$trySceneManagerSetCurrentScene_bySceneName_withSceneNameThatDoesNotExist$3(SceneManagerTests.java:146)
	at [email protected]/org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:55)
	... 93 more


Gradle Test Executor 1 finished executing tests.
> Task :test
SceneManagerTests > trySceneManagerSetCurrentScene_bySceneName_withSceneNameThatDoesNotExist() FAILED
    org.opentest4j.AssertionFailedError: Unexpected exception type thrown ==> expected: <java.lang.IllegalStateException> but was: <java.util.ConcurrentModificationException>
        at [email protected]/org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:65)
        at [email protected]/org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:37)
        at [email protected]/org.junit.jupiter.api.Assertions.assertThrows(Assertions.java:3007)
        at fastj.library.test/unittest.testcases.systems.control.SceneManagerTests.trySceneManagerSetCurrentScene_bySceneName_withSceneNameThatDoesNotExist(SceneManagerTests.java:146)
        Caused by:
        java.util.ConcurrentModificationException
            at java.base/java.util.HashMap$HashIterator.nextNode(HashMap.java:1493)
            at java.base/java.util.HashMap$ValueIterator.next(HashMap.java:1521)
            at fastj.library/tech.fastj.systems.behaviors.BehaviorManager.reset(BehaviorManager.java:111)
            at fastj.library/tech.fastj.engine.FastJEngine.exit(FastJEngine.java:557)
            at fastj.library/tech.fastj.engine.FastJEngine.forceCloseGame(FastJEngine.java:401)
            at fastj.library/tech.fastj.engine.FastJEngine.error(FastJEngine.java:432)
            at fastj.library/tech.fastj.systems.control.SceneManager.sceneExistenceCheck(SceneManager.java:360)
            at fastj.library/tech.fastj.systems.control.SceneManager.setCurrentScene(SceneManager.java:100)
            at fastj.library.test/unittest.testcases.systems.control.SceneManagerTests.lambda$trySceneManagerSetCurrentScene_bySceneName_withSceneNameThatDoesNotExist$3(SceneManagerTests.java:146)
            at [email protected]/org.junit.jupiter.api.AssertThrows.assertThrows(AssertThrows.java:55)
            ... 3 more

Code of Conduct

  • I agree to follow this project's Code of Conduct
@lucasstarsz lucasstarsz added the bug Something isn't working label Aug 9, 2021
@lucasstarsz lucasstarsz self-assigned this Aug 9, 2021
lucasstarsz added a commit that referenced this issue Aug 28, 2021
Bug Fixes:
- (#86) Fixed issue where occasional `ConcurrentModificationException`s woulc crop up thanks to slight issues with consistent multithreaded/event-based inputs (keyboard, mouse, window, etc).
lucasstarsz added a commit that referenced this issue Aug 28, 2021
@lucasstarsz lucasstarsz linked a pull request Sep 12, 2021 that will close this issue
lucasstarsz added a commit that referenced this issue Sep 12, 2021
Images, Sprites, Animations, and a lot more

Additions
-  (#104) added Linux's X11 to list of supported hardware accelerations
- (#108) Added Sprite2D and simple animation system
    - Manages an array of sprites, as well as an image resource instance
    - has default animations for "continuous", "play to end", and "static" (default is "continuous")
- (#113) Added centralized, extensible resource manager
- (#108, #113) Added image resource manager implementation
- (#108) Added `ImageUtil` to load and manage buffered images (makes use of resource manager where needed)
- (#113) Added default resource management, loaded on `FastJEngine` static initialization (_before_ `FastJEngine.init`!)
- (#10, #110) added `TexturePaint` builder, and support for `TexturePaint` in `.psdf` files
- (#10) Added support for writing/parsing `Model2D` to the `.obj`/`.mtl` file format


Bug Fixes
- (Fixes #106) Fixed translation doubling by removing translation from `setMetrics` method calls
- (Fixes #114) Added missing call to `Scene.reset` for each scene in `SceneManager` during a call to `SceneManager.reset`.
-  (Fixes #115) Added calls to destroy `Drawable`s in `Scene`/`SimpleManager`
- (Fixes #86) Fixed issue where occasional `ConcurrentModificationException`s woulc crop up thanks to slight issues with consistent multithreaded/event-based inputs (keyboard, mouse, window, etc).


Breaking Changes
- Moved `tech.fastj.systems.fio.FileUtil` to `tech.fastj.resources.files.FileUtil`
- Moved `tech.fastj.graphics.util.ModelUtil` to `tech.fastj.resources.models.ModelUtil`
- Moved `tech.fastj.graphics.io.PsdfUtil` to `tech.fastj.resources.models.PsdfUtil`
- Moved `tech.fastj.graphics.io.SupportedModelFormats` to `tech.fastj.resources.models.SupportedModelFormats`
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

1 participant