sporadic ConcurrentModificationException #39

Open
opened 2024-07-15 09:14:55 +02:00 by ni · 3 comments
ni commented 2024-07-15 09:14:55 +02:00 (Migrated from git.w21.org)

On startup, a ConcurrentModificationException happens sporadically. It is caused by tildeExpand() called by the startup Lisp code, which in turn calls a subprocess. Like sometimes seen in other contexts, the subprocess IO handling is flaky and causes this Exception. This happens more often under Linux than macOS.

java.util.ConcurrentModificationException
	at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1095)
	at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1049)
	at kotlin.collections.CollectionsKt___CollectionsKt.joinTo(_Collections.kt:3490)
	at kotlin.collections.CollectionsKt___CollectionsKt.joinToString(_Collections.kt:3510)
	at kotlin.collections.CollectionsKt___CollectionsKt.joinToString$default(_Collections.kt:3509)
	at org.w21.lyk.StrBuf.toString(div.kt:139)
	at org.w21.lyk.StringWriterStream.value_and_reset(stream.kt:164)
	at org.w21.lyk.FilesKt.tildeExpand(files.kt:154)
	at org.w21.lyk.FilesKt.tildeExpand(files.kt:154)
	at org.w21.lyk.FilesKt.bi_expand_file_name(files.kt:204)
	at org.w21.lyk.Init_builtinsKt$init_Builtins$148.invoke(init-builtins.kt:1737)
	at org.w21.lyk.Init_builtinsKt$init_Builtins$148.invoke(init-builtins.kt:1737)
	at org.w21.lyk.LBuiltin.call$lambda$0(builtin.kt:108)
	at org.w21.lyk.FunctionKt.with_called_function_name(function.kt:430)
	at org.w21.lyk.LBuiltin.call(builtin.kt:107)
	at org.w21.lyk.EvalKt.eval(eval.kt:130)
	at org.w21.lyk.BasicKt.bi_defvar(basic.kt:1467)
	at org.w21.lyk.Init_builtinsKt$init_Builtins$67.invoke(init-builtins.kt:817)
	at org.w21.lyk.Init_builtinsKt$init_Builtins$67.invoke(init-builtins.kt:817)
	at org.w21.lyk.LBuiltin.call$lambda$0(builtin.kt:108)
	at org.w21.lyk.FunctionKt.with_called_function_name(function.kt:430)
	at org.w21.lyk.LBuiltin.call(builtin.kt:107)
	at org.w21.lyk.EvalKt.eval(eval.kt:130)
	at org.w21.lyk.ReplKt.repl$lambda$1(repl.kt:72)
	at org.w21.lyk.DivKt.measurePerfdataValue$lambda$1(div.kt:258)
	at org.w21.lyk.DivKt.measurePerfdata(div.kt:271)
	at org.w21.lyk.DivKt.measurePerfdataValue(div.kt:257)
	at org.w21.lyk.ReplKt.repl(repl.kt:71)
	at org.w21.lyk.ReplKt.repl$default(repl.kt:19)
	at org.w21.lyk.LoadKt.load_stream$lambda$4$lambda$1(load.kt:88)
	at org.w21.lyk.DivKt.measurePerfdata(div.kt:271)
	at org.w21.lyk.LoadKt.load_stream$lambda$4(load.kt:87)
	at org.w21.lyk.HelpersKt.withVariableAs(helpers.kt:356)
	at org.w21.lyk.LoadKt.load_stream(load.kt:84)
	at org.w21.lyk.LoadKt.load_string(load.kt:71)
	at org.w21.lyk.LoadKt.load_string$default(load.kt:69)
	at org.w21.lyk.MainKt.main(main.kt:195)
JavaError: ConcurrentModificationException: Java error
On startup, a ConcurrentModificationException happens sporadically. It is caused by `tildeExpand()` called by the startup Lisp code, which in turn calls a subprocess. Like sometimes seen in other contexts, the subprocess IO handling is flaky and causes this Exception. This happens more often under Linux than macOS. ``` java.util.ConcurrentModificationException at java.base/java.util.ArrayList$Itr.checkForComodification(ArrayList.java:1095) at java.base/java.util.ArrayList$Itr.next(ArrayList.java:1049) at kotlin.collections.CollectionsKt___CollectionsKt.joinTo(_Collections.kt:3490) at kotlin.collections.CollectionsKt___CollectionsKt.joinToString(_Collections.kt:3510) at kotlin.collections.CollectionsKt___CollectionsKt.joinToString$default(_Collections.kt:3509) at org.w21.lyk.StrBuf.toString(div.kt:139) at org.w21.lyk.StringWriterStream.value_and_reset(stream.kt:164) at org.w21.lyk.FilesKt.tildeExpand(files.kt:154) at org.w21.lyk.FilesKt.tildeExpand(files.kt:154) at org.w21.lyk.FilesKt.bi_expand_file_name(files.kt:204) at org.w21.lyk.Init_builtinsKt$init_Builtins$148.invoke(init-builtins.kt:1737) at org.w21.lyk.Init_builtinsKt$init_Builtins$148.invoke(init-builtins.kt:1737) at org.w21.lyk.LBuiltin.call$lambda$0(builtin.kt:108) at org.w21.lyk.FunctionKt.with_called_function_name(function.kt:430) at org.w21.lyk.LBuiltin.call(builtin.kt:107) at org.w21.lyk.EvalKt.eval(eval.kt:130) at org.w21.lyk.BasicKt.bi_defvar(basic.kt:1467) at org.w21.lyk.Init_builtinsKt$init_Builtins$67.invoke(init-builtins.kt:817) at org.w21.lyk.Init_builtinsKt$init_Builtins$67.invoke(init-builtins.kt:817) at org.w21.lyk.LBuiltin.call$lambda$0(builtin.kt:108) at org.w21.lyk.FunctionKt.with_called_function_name(function.kt:430) at org.w21.lyk.LBuiltin.call(builtin.kt:107) at org.w21.lyk.EvalKt.eval(eval.kt:130) at org.w21.lyk.ReplKt.repl$lambda$1(repl.kt:72) at org.w21.lyk.DivKt.measurePerfdataValue$lambda$1(div.kt:258) at org.w21.lyk.DivKt.measurePerfdata(div.kt:271) at org.w21.lyk.DivKt.measurePerfdataValue(div.kt:257) at org.w21.lyk.ReplKt.repl(repl.kt:71) at org.w21.lyk.ReplKt.repl$default(repl.kt:19) at org.w21.lyk.LoadKt.load_stream$lambda$4$lambda$1(load.kt:88) at org.w21.lyk.DivKt.measurePerfdata(div.kt:271) at org.w21.lyk.LoadKt.load_stream$lambda$4(load.kt:87) at org.w21.lyk.HelpersKt.withVariableAs(helpers.kt:356) at org.w21.lyk.LoadKt.load_stream(load.kt:84) at org.w21.lyk.LoadKt.load_string(load.kt:71) at org.w21.lyk.LoadKt.load_string$default(load.kt:69) at org.w21.lyk.MainKt.main(main.kt:195) JavaError: ConcurrentModificationException: Java error ```
ni commented 2024-07-15 09:18:43 +02:00 (Migrated from git.w21.org)

changed the description

changed the description
ni commented 2024-07-17 08:22:53 +02:00 (Migrated from git.w21.org)

marked this issue as related to #2

marked this issue as related to #2
ni commented 2024-07-17 08:31:24 +02:00 (Migrated from git.w21.org)

Interestingly, the issue is (more or less?) avoided by a Thread.sleep(5) in bi_run_program() before considering the subprocess finished and the reader/writer threads done and reaping the results. So, I think I understand the problem now.

While a 5 ms delay is not very much in the context of running an external program (and thus bearable enough), it isn't the right way to handle this. That would be letting the threads come to a real close and thus be definitely safe of any ConcurrentModificationException. How this is done is the thing to find out.

Interestingly, the issue is (more or less?) avoided by a `Thread.sleep(5)` in `bi_run_program()` before considering the subprocess finished and the reader/writer threads done and reaping the results. So, I think I understand the problem now. While a 5 ms delay is not very much in the context of running an external program (and thus bearable enough), it isn't the right way to handle this. That would be letting the threads come to a real close and thus be definitely safe of any `ConcurrentModificationException`. How this is done is the thing to find out.
Sign in to join this conversation.
No description provided.