Handling The “badarg” Error in Erlang When Passing Messages

I am new to Erlang and trying to pass the result from one function to another using message passing. However, I am encountering badarg errors when using main ! {numbers, 1, 100}. Despite trying different changes, the message still isn’t passed correctly, especially when using From.

In the code provided, the line main ! {numbers, 1, 100} might fail because the main process is expected to be registered, and if it is not properly registered or the process has exited, Erlang will raise a badarg error. To fix this, ensure that the process main is correctly registered by calling register(main, Pid) and that the process is alive when trying to send messages. Additionally, the use of message passing with From commented out in the proc function could prevent responses from being delivered to the correct sender, further contributing to the error. Double-checking the registration of the main process and ensuring it is running when sending messages should help resolve the issue.

Erlang Code (with Errors):

code-module(numbers).
-export([start_main/0,main/2,proc/0,sumNumbers/2]).

main(Total, N) ->
if
N == 0 ->
io:format("Total: ~p ~n", [Total]);
true ->
true
end,
receive
{numbers, Low, High} ->
Half = round(High/2),
Pid1 = spawn(numbers, proc, []),
Pid2 = spawn(numbers, proc, []),
Pid1 ! {work, Low, Half},
Pid2 ! {work, Half+1, High};
%% Pid1 ! {work, self(), Low, Half},
%% Pid2 ! {work, self(), Half+1, High},
{return, Result} ->
io:format("Received ~p ~n", [Result]),
main(Total+Result, N-1)
end.

proc() ->
receive
{work, Low, High} ->
io:format("Processing ~p to ~p ~n", [Low, High]),
Res = sumNumbers(Low,High),
main ! {return, Res},
proc()
%% {work, From, Low, High} ->
%% io:format("Processing ~p to ~p ~n", [Low, High]),
%% Res = sumNumbers(Low,High),
%% From ! {return, Res},
%% proc()
end.

sumNumbers(Low, High) ->
Lst = lists:seq(Low,High),
lists:sum(Lst).

start_main() ->
register(main, spawn(numbers, main, [0,2])).

Changes made:

  1. Correct message format in proc:
    • Added the sender process (self()) when sending the work message to proc.
    • This ensures that the worker process knows which process to send the result ({return, Res}) back to.
  2. Handling responses in main:
    • main now expects responses from the two worker processes and reduces the counter N accordingly once it receives each result.
  3. Fixed message sending in proc:
    • In the proc function, we send the result back to the calling process (From) using From ! {return, Res}.

This corrected code now properly handles message passing between processes in Erlang without triggering the badarg error. The main function will correctly coordinate the workers, collect results, and print the total.

Correct Code:

code-module(numbers).
-export([start_main/0, main/2, proc/0, sumNumbers/2]).

main(Total, N) ->
if
N == 0 ->
io:format("Total: ~p ~n", [Total]);
true ->
true
end,
receive
{numbers, Low, High} ->
Half = round(High/2),
Pid1 = spawn(numbers, proc, []),
Pid2 = spawn(numbers, proc, []),
Pid1 ! {work, Low, Half, self()},
Pid2 ! {work, Half+1, High, self()},
main(Total, 2); %% Expecting two responses, so keeping N as 2.
{return, Result} ->
io:format("Received ~p ~n", [Result]),
main(Total+Result, N-1)
end.

proc() ->
receive
{work, Low, High, From} ->
io:format("Processing ~p to ~p ~n", [Low, High]),
Res = sumNumbers(Low, High),
From ! {return, Res}, %% Send the result back to the calling process
proc()
end.

sumNumbers(Low, High) ->
Lst = lists:seq(Low, High),
lists:sum(Lst).

start_main() ->
register(main, spawn(numbers, main, [0, 2])).

Fixing the badarg Error in Erlang

When learning Erlang, you might encounter the badarg error when passing messages between processes. This error typically occurs when a process is not registered or when an invalid argument is passed. Let’s break down the common causes of this error and how to resolve it.

In the provided code, the goal is to calculate the sum of a range of numbers using multiple processes. The function proc handles the actual work, while the main function coordinates the flow of the program.

The error stems from two primary issues:

  1. Unregistered or exited process: The main process needs to be registered before other processes can send messages to it. Without this registration, trying to send a message to main results in a badarg error.
  2. Message handling flow: The original main function doesn’t properly handle multiple responses from the spawned processes. The function should remain active to receive both results.

Fixes:

  1. Registering the main process: The start_main function correctly registers the main process using register(main, Pid), allowing other processes to send messages to it.
  2. Correct message flow: A recursive call to main is added after spawning the worker processes. This ensures that main stays active and is ready to receive messages from the worker processes.

By addressing these issues, the badarg error can be resolved, and the code will execute as intended.

Related blog posts