Skip to content

Signal handler in threads #81

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

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions