Understanding `global:set_lock/3`

Hello pals!

I’ve been playing about with the global module, and I don’t understand what the rules are for when a process can set a lock.

Here’s what the documentation says:

If a lock already exists on ResourceId for another requester than LockRequesterId, and Retries is not equal to 0, the process sleeps for a while and tries to execute the action later. When Retries attempts have been made, false is returned, otherwise true. If Retries is infinity, true is eventually returned (unless the lock is never released).

Here’s my test program:

#!/usr/bin/env escript
-module(lock_ness).

main(_) ->
    % Spawn multiple processes, each try to get the same lock but with a
    % different requester id.
    spawn(fun get_lock/0),
    spawn(fun get_lock/0),
    spawn(fun get_lock/0),

    % Let the program run.
    timer:sleep(1000).

get_lock() ->
    Nodes = [node()],

    % Only try once so we can immediately see the result
    Retries = 1,

    % type global:id() :: {ResourceId :: term(), LockRequesterId :: term()}.
    ResourceId = my_lock,
    LockRequesterId = self(),
    Id = {ResourceId, LockRequesterId},

    % -spec set_lock(Id, Nodes, Retries) -> boolean()
    DidGetLock = global:set_lock(Id, Nodes, Retries),

    erlang:display({self(), DidGetLock}).

My expectation was that with with 3 different processes, 3 different LockRequesterIds, and 1 ResourceId the first would successfully set the lock, while the later 2 would not be able to. However, when I run the program it seems all 3 successfully set the lock:

$ escript lock_ness.escript 
{<0.83.0>,true}
{<0.84.0>,true}
{<0.85.0>,true}

The documentation later says this:

The global name server keeps track of all processes sharing the same lock, that is, if two processes set the same lock, both processes must delete the lock.

I took this to mean that two processes using the same LockRequesterIds would be able to acquire the same lock, but with different LockRequesterIds they would not be able to.

What’s my misunderstanding here? Under what circumstances does global:set_lock/3 return false?

Thanks,
Louis

1 Like

You’re getting true since each lock is getting released.

Adding a timer:sleep(500) after DidGetLock = ... will show you

leonard@captmarvel:/tmp$ ./lock_ness.escript
{<0.84.0>,true}
{<0.86.0>,false}
{<0.85.0>,false}

Edit: from the doc for set_lock/3

If a process that holds a lock dies, or the node goes down, the locks held by the process are deleted.
1 Like

Oh of course, what a fool I am. Thank you for the help!

1 Like