[erlang-questions] enif_send, how to call off a smp thread?

Sverker Eriksson sverker.eriksson@REDACTED
Tue Mar 21 16:47:18 CET 2017


I think I know the answer: single assignment.

Try flush() in the shell and get all messages,
even those that don't match X :-)


/Sverker


On 03/21/2017 03:59 PM, Vans S wrote:
> Im going to try that, for now I made a test case that fails for me
> https://github.com/vans163/nif_test.
>
> The 3rd receive we get ok instead of 56.
>
> I am on Erlang 19.1.2 though, maybe I should try the R19.3 or master HEAD?
>
>
>
> On Tuesday, March 21, 2017 10:28 AM, Sverker Eriksson <sverker.eriksson@REDACTED> wrote:
>
>
>
> enif_send can be called from a non scheduler thread in an SMP enabled VM
> (beam.smp)
> but not in a non-SMP VM (beam).
>
> The outcome being dependent on the message term sounds very strange.
>
>
> Run with debug compiled VM to get more runtime sanity checks.
>
>
> $> (cd $ERL_TOP/erts/emulator && make TYPE=debug smp)
>
> $> $ERL_TOP/bin/cerl -debug
>
>
> /Sverker
>
>
>
> On 03/21/2017 02:57 PM, Vans S wrote:
>> Iv tried so many combinations of passing the default env in the user_data of the callback/setting a global or setting that to NULL and using the msg_env, same result. Even if I do it like this or that:
>>
>> static ErlNifPid my_temp_pid;
>> static void on_callback(void* user_data)
>> {
>> ErlNifEnv* msg_env = enif_alloc_env();
>>
>> enif_send(NULL, &my_temp_pid, msg_env, mk_atom(msg_env, "okk"));
>> enif_free_env(msg_env);
>>
>> msg_env = enif_alloc_env();enif_send(NULL, &my_temp_pid, msg_env, mk_atom(msg_env, "aaokk"));
>> enif_free_env(msg_env);
>> }
>>
>>
>> static void on_callback2(void* user_data)
>> {
>> ErlNifEnv* msg_env = enif_alloc_env();
>> enif_send(NULL, &my_temp_pid, msg_env, mk_atom(msg_env, "okk"));
>> enif_clear_env(msg_env);
>> enif_send(NULL, &my_temp_pid, msg_env, mk_atom(msg_env, "aaokk"));
>> enif_free_env(msg_env);
>> }
>>
>>
>> Only the first msg comes, its like it caches/remembers it and ignores the rest. I wonder if its due to not being able to
>> call enif_send from a random non SMP thread and if I need to make a queue that I poll later?
>>
>> By only the first msg comes, if I later do a enif_send with "okk2" atom as the first, it wont send unless the atom is exactly "okk".
>>
>> The same thing if you substitute the atom with an integer or binary.
>>
>> On Tuesday, March 21, 2017 6:52 AM, Sverker Eriksson <sverker.eriksson@REDACTED> wrote:
>>
>>
>>
>> enif_send docs says:
>>
>> "The message environment msg_env with all its terms (including msg)
>> is invalidated by a successful call to enif_send. The environment is to
>> either be freed with enif_free_env of cleared for reuse with
>> enif_clear_env."
>>
>> which means you have to call enif_clear_env before reusing msg_env
>> in the second call to enif_send.
>>
>> Or if you're running OTP 19 you can pass msg_env as NULL,
>> in which case the message term is copied and its environment left intact
>> by enif_send.
>>
>>
>> /Sverker, Erlang/OTP
>>
>>
>>
>> On 03/21/2017 05:10 AM, Vans S wrote:
>>> I am having a weird issue with enif_send.
>>>
>>> What is happening is I am interoping with a 3rd party C library which has
>>> its own event loop and procs callbacks from its own thread.
>>>
>>> When the callback procs (in the C NIF) I want to call enif_send to get
>>> the message back to an erlang pid.
>>>
>>> When I call enif_send the first term I pass it works, then every subsequent message
>>> gets dropped unless its exactly the same as the first time passed.
>>>
>>> For example
>>>
>>>
>>> static ErlNifPid my_temp_pid;
>>> static void on_callback(void* user_data)
>>> {
>>> ErlNifEnv* msg_env = enif_alloc_env();
>>> enif_send(NULL, &my_temp_pid, msg_env, mk_atom(msg_env, "okk"));
>>> enif_send(NULL, &my_temp_pid, msg_env, mk_atom(msg_env, "aaokk"));
>>> enif_free_env(msg_env);}
>>>
>>> *on_callback proced
>>> 6> receive X-> X after 1 -> none end.
>>> okk
>>>
>>> 7> receive X-> X after 1 -> none end.none
>>> *on_callback proced
>>> 8> receive X-> X after 1 -> none end.
>>> okk
>>> 9> receive X-> X after 1 -> none end.
>>> none
>>> *on_callback proced
>>> *on_callback proced
>>> 10> receive X-> X after 1 -> none end.
>>> okk
>>> 11> receive X-> X after 1 -> none end.
>>> okk
>>> 12> receive X-> X after 1 -> none end.
>>> none
>>> What is the correct way to do this? Thanks.
>>> _______________________________________________
>>> erlang-questions mailing list
>>> erlang-questions@REDACTED
>>> http://erlang.org/mailman/listinfo/erlang-questions
>> _______________________________________________
>> erlang-questions mailing list
>> erlang-questions@REDACTED
>> http://erlang.org/mailman/listinfo/erlang-questions
>>
> _______________________________________________
> erlang-questions mailing list
> erlang-questions@REDACTED
> http://erlang.org/mailman/listinfo/erlang-questions
>




More information about the erlang-questions mailing list