erlang:open_port

Roger Lipscombe roger@REDACTED
Sat Jun 13 15:06:25 CEST 2020


Random shot in the dark: does it only go wrong on Windows?

I'm thinking that 10 is line-feed (LF), and that Windows stdout is
converting it to CRLF and so you're seeing a 13, followed by a 10, and
that's screwing everything up.

If that's the case, set stdout to binary (e.g.
https://stackoverflow.com/questions/5813301/how-c-output-lf-to-stdout-without-being-changed-to-cr-lf).

On Sat, 13 Jun 2020 at 07:05, 史研 <419719104@REDACTED> wrote:
>
> Hi,
>
> I'm sorry, my previous question is not clear.
>
> I start a external process by erlang:open_port, and use two bytes for message length. But erlang process will not receive the message when the message's length of external process return is 10 bytes, and it will lead to all the follow messages can't be received. Using OTP 19.
>
> This is how I'm using it:
>
> %% erlang
> init([Src]) ->
>     erlang:process_flag(trap_exit, true),
>     ServerId = erlang:integer_to_list(args_system:get_sid(Src)),
>     Port = case os:type() of
>                {win32, _} ->
>                    open_port({spawn_executable, "./erlc_win32"}, [{packet, 2}, {args, [ServerId]}]);
>                _ ->
>                    open_port({spawn_executable, "./erlc_unix"}, [{packet, 2}, {args, [ServerId]}])
>            end,
>     {ok, #state{port = Port}}.
>
> handle_call({call, Cmd, Msg}, From, #state{port = Port} = State) ->
>     case call_encode(Cmd, From, Msg) of
>         false ->
>             {reply, false, State};
>         Data ->
>             Port ! {self(), {command, Data}},
>             {noreply, State}
>     end;
> handle_call(_Request, _From, State) ->
>     {reply, ok, State}.
>
> handle_info({Port, {data, Data}}, #state{port = Port} = State) ->
>     io:format("Len = ~p~n", [length(Data)]),
>     case decode(Data) of
>         {From, Msg} ->
>             z_lib:reply(From, Msg);
>         _ ->
>             ok
>     end,
>     {noreply, State};
> handle_info({'EXIT', Port, Reason}, #state{port = Port} = State) ->
>     exit(Reason),
>     {noreply, State};
> handle_info(_Info, State) ->
>     {noreply, State}.
>
> // c
> int main(int argc, char* argv[]) {
> int i;
> char out[1000] = {0};
> for(i = 0; i < 1000; ++i)
> {
> strcat(out, "|");
> write_cmd(out, strlen(out));
> }
> }
>
> int write_cmd(unsigned char* buf, int len)
> {
> char li;
> li = (len >> 8) & 0xff;
> write_exact(&li, 1);
> li = len & 0xff;
> write_exact(&li, 1);
> return write_exact(buf, len);
> }
>
> int write_exact(unsigned char* buf, int len)
> {
> int i, wrote = 0;
> while (wrote < len)
> {
> if ((i = write(1, buf + wrote, len - wrote)) <= 0)
> return (i);
> wrote += i;
> }
> return(len);
> }
>
> See attachment for test result.
>
> If I modify the write_cmd function as follows, it will runs correct.
>
> int write_cmd(unsigned char* buf, int len)
> {
> if ((len & 0xff) == 10)
> {
> len += 1;
> }
> char li;
> li = (len >> 8) & 0xff;
> write_exact(&li, 1);
> li = len & 0xff;
> write_exact(&li, 1);
> return write_exact(buf, len);
> }
>
>


More information about the erlang-questions mailing list