aboutsummaryrefslogtreecommitdiff
path: root/tests/deadlock.lua
blob: d028e83f9d753d36a7e751fed472de08df28c15b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
-- this script tests the fix of a bug that could cause the mutex of a keeper state to remain locked
-- see https://github.com/LuaLanes/lanes/commit/0cc1c9c9dcea5955f7dab921d9a2fff78c4e1729

local lanes = require "lanes"

-- Lua 5.1 compatibility
local table_unpack = table.unpack or unpack

local SLEEP = function(...)
    local k, v = lanes.sleep(...)
    assert(k == nil and v == "timeout")
end

print "let's begin"

local do_extra_stuff = true

if do_extra_stuff then
    local linda = lanes.linda "deadlock_linda"
    -- just something to make send() succeed and receive() fail
    local payload = { io.flush }

    -- lane generator. don't initialize "io" base library so that it is not known in the lane
    local g = lanes.gen('base,table', function()
        lane_threadname( "deadlock_lane")
        -- wrapping inside pcall makes the Lanes module unaware that something went wrong
        print( "In lane 1:", table_unpack{ pcall( linda.receive, linda, 'tmp')})
        -- with the bug not fixed, and non-recursive mutexes, we can hang here
        print( "In lane 2:", table_unpack{ pcall( linda.receive, linda, 'tmp')})
        -- return something out of the lane
        return 33, 55
    end)

    -- send payload twice. succeeds because sending stores a function identification string in the linda's keeper state
    linda:send( 'tmp', payload, payload)
    -- start the lane
    local h = g()
    -- wait for lane completion
    local err, stack = h:join()
    print( 'result of lane execution', err, stack)
end

-- With the bug not fixed, the linda keeper's mutex is still acquired,
-- and the program hangs when the internal linda used for timers attempts to acquire the same keeper (there is only one by default)
print('waiting a bit')
SLEEP(2)
print('we should reach here')