简体   繁体   中英

Can't spawn process in Erlang

I'm not quite sure why I can't get this but I'm sure the answer is extraordinarily simple. I'm just testing out a few things and in my tests discovered that I would like to spawn a process within handle_info of my gen_server .

However despite me trying different combinations the best result I'm getting from my child is dying with an error and returning {undef, [{bob, hello, [], []}]} .

Code:

-module(test).
-behaviour(gen_server).
-export([start_link/1, init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2, code_change/3]).

start_link(Args) ->
    gen_server:start_link({local, Args}, ?MODULE, Args, []).

init(Args) ->
    io:format("Init ~p ~p~n",[self(), Args]),
    {ok, Args}.

handle_call(_, _, State) ->
    io:format("Call ~p~n",[self()]),
    {reply, ok, State}.

handle_cast(_, State) ->
    io:format("Cast ~p~n",[self()]),
    {noreply, State}.

handle_info(_, State) ->
    io:format("Info ~p~n",[self()]),
    spawn(?MODULE,fun hello/1,[]),
    {noreply, State}.

terminate(_, _) ->
    ok.

code_change(_, State, _) ->
    {ok, State}.

hello([]) ->
    io:format("WOOT ~p~n",[self()]).

My first goal was to determine if multiple servers could be started with one module. The second was if handle_info was executed in a separate process... for some reason when I read it was asynchronous I thought it was in another process. Now the third is to spawn a process within that call.

My typical shell goes something like (with comments):

> c(test), {ok, P} = gen_server:start_link(bob)
> %% Warns me the function hello in any incarnation is not used
> P ! woot.
> %% An error of some kind depending on what I've done
> f(P), gen_server:stop(bob).

I've used hello/1 with [] and _ , hello/0 . As well as spawn/1 , spawn/3 , spawn_link/1 and spawn_link/3 ... I've used ?MODULE , test , State and for chuckles {local, State} as the module parameter. I've parted with what I've seen on multiple websites and put in fun hello/0 and fun hello/1 when passing the function. This produces crashes but got rid of the compiler warning.

Where did I go wrong?

The third argument to spawn/3 is a list containing the number of arguments which the spawned function requires. For instance, if the spawned function takes 1 argument, the list will contain 1 argument; and if the spawned function takes 3 arguments, the list will contain 3 arguments. Finally, if the spawned function takes 0 arguments, the list will contain 0 arguments, ie the empty list.

You defined hello like this:

hello([]) ->
    io:format("WOOT ~p~n",[self()]).

That's a function with arity 1, and not only that, the only argument that matches the function is the empty list. In order to pass one argument to a function that you spawn, you would have to write:

spawn(?MODULE, hello ,[SomeArg])

And, because you want to match a function that takes the empty list as its only argument, SomeArg has to be the empty list:

spawn(?MODULE, hello, [[]])

Note that the syntax for spawn/3 is MFA, or module name, function name, arguments, which is a list containing the arguments.

Next, you have two more problems:

  1. You shouldn't call gen_server:start_link(bob) as you did here:

     {ok, P} = gen_server:start_link(bob)

    There is no such function as gen_server:start_link/1 . Instead, you need to call your user interface function start_link/1 , which then calls gen_server:start_link/3 . You might want to rename your user interface function my_gen_server_starter() , so that you are clear about what it does.

  2. %% Warns me the function hello in any incarnation is not used

    You have to export a function to be able to spawn it. Because you didn't export the function and because no functions inside the module call the function, that means the function can never execute.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM