potatosalad / elixirconf2017

Well-Behaved Native Implemented Functions for Elixir
https://gitpitch.com/potatosalad/elixirconf2017
32 stars 2 forks source link

Need help with enif_select() #1

Open rushikesh1 opened 5 years ago

rushikesh1 commented 5 years ago

I am trying to write a code in nif which will work asynchronously.

For that I am referring code for tcp server code for normal select() (refer link https://www.cs.cmu.edu/afs/cs/academic/class/15213-f99/www/class26/tcpserver.c) I wrapped this code in a function say listen() and invoked it in a erlang function start() as shown in below snippet

This start() has two process spawned spawn(server, listen, [3]), spawn(server, say_something, [goodbye, 3]).

And as per my expectation I want say_something() to be executed in parallel with listen(). For this I replaced select() call in tcpserver.c with enif_select() as below

ERL_NIF_TERM temp;
ERL_NIF_TERM atom_undefined;
 ErlNifResourceTypeInit rt_init = {NULL, ttsl_rt_stop};
 ttsl_resource_type = enif_open_resource_type_x(env, "tty_sl", &rt_init,
                                               ERL_NIF_RT_CREATE, NULL);
ttsl_resource = enif_alloc_resource(ttsl_resource_type, sizeof(struct ttsl_resource_t));
enif_select(env, parentfd, ERL_NIF_SELECT_WRITE, ttsl_resource, NULL, atom_undefined);

But this code is not working as expected and it is generating core in scheduler. Can you please guide me with this ? Please let me know If you want me to share complete code.


-module(server). -export([foo/1,start/0, say_something/2]). -on_load(init/0).

init() -> ok = erlang:load_nif("./tcpserver", 0).

listen(_X) -> exit(nif_library_not_loaded).

say_something(What, 0) -> done; say_something(What, Times) -> io:format("~p~n", [What]), say_something(What, Times - 1).

start() -> spawn(server, listen, [3]), spawn(server, say_something, [goodbye, 3]).

potatosalad commented 5 years ago

@rushikesh1 Could you provide a gist or a repository where I can see the complete code?

rushikesh1 commented 5 years ago

Hi @potatosalad . Sorry for trouble and late response.

Here is gist for code https://gist.github.com/rushikesh1/e351af7800be91a564481c81e32df1dd

I have slightly modified your code and I am able to run it on unix but I am still facing issues on Windows. enif_select() is not working for me in case of windows.

I have made few changes in your code. In connect_nif() I am creating a ListenSocket for windows similar to what you did for unix. And in recv_try_nif() I am accepting new connections on this ListenSocket. Once I get clientSocket I wanted to pass this socket back to erlang module for performing further read/write on this socket. But currently I am doing read/write in same recv_try_nif() .

The problem I am facing is the sverk_tcp_nif.erl is not recieving {select, Rsrc, Ref, ready_input} though there is new connections recived on ListenSocket which is passed to nif_select() .

Can you please let me know what am I missing in case of windows ?