typelead/eta

Error calling with java a exported function by eta in a multi-thread environment

Boreaso opened this issue · 4 comments

Description

I want to export a function like this:

foreign export java "@static eta.example.MyClass.sayAnything" sayAnythingEta :: String -> IO ()
sayAnythingEta text = do
putStrLn text
return text

How can I call it in java. Further more, how call I call it in java multi-thread mode.

I try to run it in java multi-thread environment, then I got exceptions:

Exception in thread "pool-1-thread-5" eta.runtime.exception.EtaException: thread blocked indefinitely in an MVar operation
at eta.runtime.stg.Capability.detectMVarDeadlock(Capability.java:703)
at eta.runtime.stg.Capability.idleLoop(Capability.java:690)
at eta.runtime.stg.Capability.blockedLoop(Capability.java:728)
at eta.runtime.stg.Capability.blockedLoop(Capability.java:724)
at eta.runtime.concurrent.Concurrent.takeMVar(Concurrent.java:71)
at base.ghc.io.handle.Internals$$wa2.call(Internals.hs:164)
at base.ghc.io.handle.Internals$a3.applyV(Internals.hs:133)
at eta.runtime.exception.Exception.maskAsyncExceptions(Exception.java:42)
at base.ghc.io.handle.Internals$$wa4.call(Internals.hs:131)
at base.ghc.io.handle.Internals$$wa3.call(Internals.hs:237)
at base.ghc.io.handle.Internals$wantWritableHandle1.call(Internals.hs:227)
at base.ghc.io.handle.Text$hPutStr2.call(Text.hs:544)
at main.Main$$fe_sayHelloEta1.call(Main.hs:10)
at main.Main$$fe_sayHelloEta.call(Main.hs:9)
at main.Main$$fe_sayHelloEta.applyV(Main.hs:9)
at eta.runtime.stg.Closures$EvalIO.enter(Closures.java:177)
at eta.runtime.stg.Capability.schedule(Capability.java:246)
at eta.runtime.stg.Capability.scheduleClosure(Capability.java:202)
at eta.runtime.Runtime.evalIO(Runtime.java:400)
at eta.example.Duckling.sayHello(Unknown Source)
at Main$1.run(Main.java:18)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
at java.lang.Thread.run(Thread.java:748)

Please help me!

Hi! I think you have made a typo in your example, i suppose it is:

foreign export java "@static eta.example.MyClass.sayAnything" sayAnythingEta :: String -> IO ()
sayAnythingEta text = do
  putStrLn text
  return ()

I've just test something similar with lastest etlas and eta and it worked for me.
What do you mean with "java multi-thread environment"?

@jneira Hello, jneira, thank you for your answer. Actually, my program is multi-threaded, I want to call this function in multi-threaded state. Just like this:

public static void main(String[] args) {
        ThreadPoolExecutor threadPool = (ThreadPoolExecutor) Executors.newFixedThreadPool(100);

        long t0 = System.currentTimeMillis();

        for (int i = 0; i < 10; i++) {
            threadPool.execute(new Thread() {
                @Override
                public void run() {
                     eta.example.MyClass.sayAnything("Hello eta.");
                }
            });
        }

        threadPool.shutdown();
        try {
            threadPool.awaitTermination(Long.MAX_VALUE, TimeUnit.MINUTES);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        long t1 = System.currentTimeMillis();

        System.out.println("Time: " + (t1 - t0));
}

How can I achieve this?

I've reproduced the error in a test project: https://github.com/jneira/eta-test/blob/print-ffi/java/Utils.java#L47-L71
It may be a bug in the runtime (maybe @rahulmutt could confirm it)

@rahulmutt Is there any solution to this problem?