Logging from nif (and especially from rust nif)

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Logging from nif (and especially from rust nif)

Max Lapshin-2

Hi.

I'm playing now with rust nif and can advice nice library:  https://github.com/hansihe/rustler

For those of us, who do not understand what is there about elixir: don't worry, no need to use it, there should be a simple makefile for compiling rust.


I've met stange situation while using println!  mechanism in rust nif  (I'm speaking about enterprise real world debugging: as lot of prints as possible).  Nif crashes from println.

if you are lucky to catch debug message, you will see something like:

stack backtrace:

   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace

   1: std::sys_common::backtrace::_print

   2: std::panicking::default_hook::{{closure}}

   3: std::panicking::default_hook

   4: std::panicking::rust_panic_with_hook

   5: std::panicking::begin_panic


or even info about error code 35.


Problem is that stdout is in non-blocking mode and when rust tries to write output, it gets error that it is not waiting for.

I've decided not to change anything in rust stdlib, but use another mechanism:

1) take pid of output writing process

2) send messages to it from rust.


Here is the way to get whom to send IO request messages:

logger() ->

  UserDrv = whereis(user_drv),

  CurGroup = case (is_pid(UserDrv) andalso process_info(UserDrv, dictionary)) of

    {dictionary, UserDrvDict} ->

      proplists:get_value(current_group, UserDrvDict);

    _ ->

      undefined

  end,

  case is_pid(CurGroup) of

    true ->

      CurGroup;

    false ->

      {_,GL} = process_info(self(),group_leader),

      GL

  end.



and here is how do I log there from rust:


  if let Some(ref logger) = mpegts.logger {
    env.pid();
    env.send(logger, (
      atoms::io_request().encode(env),
      env.pid().encode(env),
      atoms::ok().encode(env),
      (
        atoms::put_chars().encode(env), 
        atoms::unicode().encode(env), 
        (string+"\n").encode(env)
      ).encode(env)
    ).encode(env))
  }


One simple hack here: I do not send Mref as 3'rd argument, but I send atom ok. Seems to be working.




_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Logging from nif (and especially from rust nif)

Daniel Goertzen-3
The suggestion from https://github.com/rust-lang/rust/issues/24821 is to use writeln! instead of println! so you can handle the WOULDBLOCK situation yourself instead of panicing.  But, shooting all the messages over to the Erlang side seems to solve your problem.

On Sun, Sep 17, 2017 at 2:28 PM Max Lapshin <[hidden email]> wrote:

Hi.

I'm playing now with rust nif and can advice nice library:  https://github.com/hansihe/rustler

For those of us, who do not understand what is there about elixir: don't worry, no need to use it, there should be a simple makefile for compiling rust.


I've met stange situation while using println!  mechanism in rust nif  (I'm speaking about enterprise real world debugging: as lot of prints as possible).  Nif crashes from println.

if you are lucky to catch debug message, you will see something like:

stack backtrace:

   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace

   1: std::sys_common::backtrace::_print

   2: std::panicking::default_hook::{{closure}}

   3: std::panicking::default_hook

   4: std::panicking::rust_panic_with_hook

   5: std::panicking::begin_panic


or even info about error code 35.


Problem is that stdout is in non-blocking mode and when rust tries to write output, it gets error that it is not waiting for.

I've decided not to change anything in rust stdlib, but use another mechanism:

1) take pid of output writing process

2) send messages to it from rust.


Here is the way to get whom to send IO request messages:

logger() ->

  UserDrv = whereis(user_drv),

  CurGroup = case (is_pid(UserDrv) andalso process_info(UserDrv, dictionary)) of

    {dictionary, UserDrvDict} ->

      proplists:get_value(current_group, UserDrvDict);

    _ ->

      undefined

  end,

  case is_pid(CurGroup) of

    true ->

      CurGroup;

    false ->

      {_,GL} = process_info(self(),group_leader),

      GL

  end.



and here is how do I log there from rust:


  if let Some(ref logger) = mpegts.logger {
    env.pid();
    env.send(logger, (
      atoms::io_request().encode(env),
      env.pid().encode(env),
      atoms::ok().encode(env),
      (
        atoms::put_chars().encode(env), 
        atoms::unicode().encode(env), 
        (string+"\n").encode(env)
      ).encode(env)
    ).encode(env))
  }


One simple hack here: I do not send Mref as 3'rd argument, but I send atom ok. Seems to be working.



_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions
Reply | Threaded
Open this post in threaded view
|

Re: Logging from nif (and especially from rust nif)

Max Lapshin-2
It also don't break current input and give more synchronized printing.

_______________________________________________
erlang-questions mailing list
[hidden email]
http://erlang.org/mailman/listinfo/erlang-questions