Skip to content

Signal handler in threads #81

Open
@YurongYou

Description

@YurongYou

I found that it seems impossible to register a signal handler in thread pools, see code below

-- test.lua
local classic = require 'classic'
local threads = require 'threads'
threads.Threads.serialization('threads.sharedserialize')
local tds = require 'tds'
local signal = require 'posix.signal'

local threadsTest = classic.class('threadsTest')

function threadsTest:_init()
    self.ctrlPool = threads.Threads(1)
    self.ctrlPool:addjob(function ()
        __threadid = 0
        local signal = require 'posix.signal'

        signal.signal(signal.SIGINT, function(signum)
            print('\nSIGINT received')
            print('Ex(c)iting')
            atomic:set(-1)
        end)
    end)
    self.ctrlPool:synchronize()
    local atomic = tds.AtomicCounter()
    atomic:set(1)
    self.nThreads = 2
    self.game = threads.Threads(self.nThreads,
        function ()
            inner = atomic
        end)
end

function threadsTest:start()
    for i = 1, self.nThreads do
        self.game:addjob(function ()
            while true do
                if inner:get() < 0 then break end
            end
        end)
    end

    self.game:synchronize()
    self.game:terminate()
end

test = threadsTest()
test:start()

the running result is just ignore the signal...

> th test.lua
^C^C^C^C^C^C^C^C

But I do see some one setting the signal handler in threadpool, see https://github.com/Kaixhin/Atari/blob/master/async/AsyncMaster.lua from line 117

And it's also weird if I call os.execute() in thread pool

-- threadTester.lua
local classic = require 'classic'
local threads = require 'threads'
threads.Threads.serialization('threads.sharedserialize')
local tds = require 'tds'
local threadTester = classic.class('threadTester')

function threadTester:_init(atomic)
    self.game = threads.Threads(1,
    function ()
        inner = atomic
    end)
    self.atomic = atomic
    classic.strict(self)
end

function threadTester:play()
    self.game:addjob(function ()
        os.execute("sleep ".. 10)
    end)
    -- do some stuff outside
    while true do
        if self.atomic:get() < 0 then break end
    end
end

return threadTester
-- test.lua
local threads = require 'threads'
threads.Threads.serialization('threads.sharedserialize')
local tds = require 'tds'
local signal = require 'posix.signal'

-- local ctrlpool = threads.Threads(1, function ()
--  local tds = require 'tds'
-- end)

local atomic = tds.AtomicCounter()
atomic:set(1)
nThreads = 4
-- local ctrlPool = threads.Threads(1)
-- ctrlPool:addjob(function ()
    local signal = require 'posix.signal'
    signal.signal(signal.SIGINT, function(signum)
        print('\nSIGINT received')
        print('Ex(c)iting')
        atomic:set(-1)
    end)
-- end)

-- ctrlPool:synchronize()

local gamePool = threads.Threads(nThreads, function ()
    threadTester = require 'threadTester'
    player = threadTester(atomic)
end)

for i = 1, nThreads do
    gamePool:addjob(function ()
        print(string.format("begin in thread %d", __threadid))
        local status, err = xpcall(player.play, debug.traceback, player)
        if not status then
            print(string.format('%s', err))
            os.exit(128)
        end
    end)
end

gamePool:synchronize()
gamePool:terminate()

here is the test result

> th test.lua
begin in thread 1
begin in thread 2
begin in thread 3
begin in thread 4
^C^C^C^C^C
SIGINT received
Ex(c)iting

I am now doing a project where I need to call a game to execute using os.execute() in each thread while collecting info... But I found that the signal handler is not functioning well...

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions