It gets even weirder.
I made an Erlang program for testing the port weirdness:
[code]#!/usr/bin/env escript
main(_args) ->
Port = open_port({spawn, “./tested.esh”}, [binary, use_stdio, {packet, 2}]),
Command1 = {init, << "127.0.0.1" >>, << "7777" >>, << "127.0.0.1" >>, << "8888" >>},
port_command(Port, term_to_binary(Command1)),
receive
{Port, {data, Result}} -> io:format("~p~n", [binary_to_term(Result)])
end,
Command2 = {eu_user_register, 5555},
port_command(Port, term_to_binary(Command2)),
receive
{Port, {data, Result2}} -> io:format("~p~n", [binary_to_term(Result2)])
end,
port_close(Port).
[/code]
I then proceeded to test it against first an Erlang script doing what is expected:
[code]#!/usr/bin/env escript
main(_args) ->
loop().
loop() ->
Input = io:get_chars(standard_io, “”, 2),
case Input of
eof -> ok;
_any ->
<< Length:16 >> = iolist_to_binary(Input),
Command = io:get_chars(standard_io, “”, Length),
Decoded = binary_to_term(iolist_to_binary(Command)),
io:format(standard_error, “got: ~p~n”, [Decoded]),
Response = term_to_binary(ok),
ResponseLen = byte_size(Response),
BinResponse = << ResponseLen:16, Response/binary >>,
io:put_chars(standard_io, binary_to_list(BinResponse)),
loop()
end.[/code]
I then test it against my elixir program that has IO.read(2)
(and no other reads on :stdio). It works as well.
When using the elixir escript, IO.read/1
and :io.get_chars/2
both behave incorrect.
In the Erlang scripts based on the same OTP, in the iex shell, and the erl shell, the respective functions work as expected.
The Erlang samples prove that if Erlang is driving the port everything works fine. If Erlang is the application running inside the port the IO works fine as well, so it is not the Beam VM and whether it is being piped into.
This issue is strictly elixir. Not Beam VM. Not the underlying OTP.