mindok

mindok

Killing java processes started from Port.open

Hi all, my current work involves interacting with MS Project files. The binary file format is pretty tedious to interact with. The best third party library I have found for reading the files is written in Java.

I have written a small test Java project that I have interoperating with a test Elixir project following guidance from this post The Erlangelist - Outside Elixir from @sasajuric.

The only problem is that the java program doesn’t die when the owning BEAM process dies or BEAM is terminated. This is discussed here: [erlang-questions] How do you kill an OS process that was opened with open_port on a brutal_kill?, and it sounds like it all relies on the program invoked by Port.open being “well-behaved” and shutting down if the stdin channel is killed.

I have trawled the Java docs and aside from realising how convoluted the process is for writing anything useful in Java (compared with Elixir), I haven’t found anything to help.

So the questions are:

  1. has anyone managed to get a well-behaved interop between Java and Elixir using Ports.
  2. If so, what does your main System.in reading code look like / how did you solve the problem of shutting down the java program without explicit termination commands from the Elixir side
  3. If not, what are the preferred options for Java interop. I am aware of JInterface but wanted to keep operational complexity down as far as possible and also minimise the amount of Java code.

I know this is probably a Java problem rather than an Elixir problem, but the Ports style interop for long-running processes through stdin/stdout does seem to be unique to Erlang/Elixir.

Edit: Only tries on Windows so far. Will year on Linux tomorrow.

Thanks!

Marked As Solved

sasajuric

sasajuric

Author of Elixir In Action

Yes, if you want proper cleanup, the external program has to be well-behaved. I’ve briefly touched on that in the article, in the “program termination” section. So basically, you need to make the Java program terminate if you receive EOF on stdin. No idea how this can be done in Java, but I’d be surprised if this wasn’t possible :slight_smile:

If you don’t control the external program, you could use erlport, which will automatically terminate the external program if the owner beam process (or the entire beam node) stops.

Also Liked

jayjun

jayjun

Creator of Rambo here. Don’t use libraries if you’re writing your own port. Libraries are for working around external programs that cannot be changed.

Your minimal program is a good start, just need to read (block on) standard input on another thread so your MS Project job can run.

If you don’t care about JVM startup time, just run your port with System.cmd on demand. Otherwise if your Java process is long-lived, you’ll need to consider the communication protocol between your Java and Erlang processes.

mindok

mindok

OK, problem exists between chair & keyboard. My main loop was badly behaved. I stripped it back to the most basic stdin read loop and it terminates ok. Time to start building it up again and see where it fails.

For reference, here’s a minimal Java program that works nicely over ports, terminating when the process or BEAM terminates (including brutally killing from Windows task manager):

package com.thing;
import java.io.*;

public class Main {
    public static void main(String[] args) throws IOException {
        int ch;
        while(true) {
            ch = System.in.read();
            if (ch == -1) {break;} // This is the EOF signal in Java
            if (ch == 'q') {break;}
            if (ch == 't') {System.out.println("tasks");}
            System.out.println(" got " + ch + " - " + (char)ch);
        }
    }
}
jayjun

jayjun

Thanks for the mention. To clarify, Rambo only requires the Rust compiler if you are not using Linux, macOS or Windows. Bundled binaries should cover most users.

Where Next?

Popular in Questions Top

skosch
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a > b) do {:ok, "a"} end if (a < b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
vegabook
I’m brand new to Phoenix and I have stripped one of the demo applications to the bone. I just want to get an svg up on the screen. Here i...
New
stefanluptak
Hello everybody, usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
lucidguppy
I have a super simple question about elixir - how would I take a file like this foo bar baz and output a new file that enumerates th...
New
RisingFromAshes
I’ve read in another post that it may be possible with a router helper - but I couldn’t find an appropriate one, and tbh, I’m still just ...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New

Other popular topics Top

danschultzer
None of the current solutions worked well for me, so I went ahead and built a user management system from scratch. This project took far...
548 29377 241
New
mcarvalho
What is the difference between System.get_env and Application.get_env? For example, what are best practices to use one versus another.
New
albydarned
Hello all! I am typing this post from my new MacBook Pro with the M1 chip. I’m loving it so far, and will probably use it as my daily dr...
New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
New
dokuzbir
I want to highlight html closing tags when i click a html tag. That works in .html files but doesnt work for html.eex templates. How can...
New
SoCreat
i’m a new one to elixir which editor can i use vs code? or atom? Thanks! :smiley:
New
Emily
I have VueJS GUIs with the project generated using Webpack. I have Elixir modules that will need to be used by the VueJS GUIs. I forese...
New
jason.o
In the code below, if the create action is not set to accept “extra_key” as an input, it errors out with a message shown above. Is there ...
New
Brian
What is the proper way to load a module from a file in to IEX? In the python world, doing something like this pretty standard: from ....
New

We're in Beta

About us Mission Statement