summaryrefslogtreecommitdiff
path: root/xmake/core/base/process.lua
diff options
context:
space:
mode:
authorruki <[email protected]>2017-06-29 10:23:38 +0800
committerruki <[email protected]>2017-06-29 10:23:38 +0800
commit741d881be8b5f0ba62dd38bdb5f7fe32909f1263 (patch)
tree3e2a479cd5a482eae1da00614dacd037edf3fb20 /xmake/core/base/process.lua
parentc45a4613ce40f939b52c2ccd883712ff30d54dcc (diff)
avoid detect the same program in the same time leading to deadlock
Diffstat (limited to 'xmake/core/base/process.lua')
-rw-r--r--xmake/core/base/process.lua104
1 files changed, 57 insertions, 47 deletions
diff --git a/xmake/core/base/process.lua b/xmake/core/base/process.lua
index 8cf96b2ea..76af563b4 100644
--- a/xmake/core/base/process.lua
+++ b/xmake/core/base/process.lua
@@ -101,53 +101,51 @@ function process.runjobs(jobfunc, total, comax, timeout, timer)
-- wait processes
local tasks_finished = {}
local procs_count = #procs
+ local procs_infos = nil
if procs_count > 0 then
-
- -- wait them
- local count, procinfos = process.waitlist(procs, utils.ifelse(procs_count < comax and index <= total, 0, timeout))
+ local count = -1
+ count, procs_infos = process.waitlist(procs, utils.ifelse(#tasks < comax and index <= total, 0, timeout))
if count < 0 then
return false, string.format("wait processes(%d) failed(%d)", #procs, count)
end
+ end
- -- timer is triggered? call timer
- if timer and os.mclock() - time > timeout then
- timer(indices)
- time = os.mclock()
- end
-
- -- wait ok
- for _, procinfo in ipairs(procinfos) do
-
- -- the process info
- local proc = procinfo[1]
- local procid = procinfo[2]
- local status = procinfo[3]
-
- -- check
- assert(procs[procid] == proc)
-
- -- resume this task
- local job_task = tasks[procid]
- local ok, job_proc_or_errors = coroutine.resume(job_task, 1, status)
- if not ok then
- return false, job_proc_or_errors
- end
+ -- timer is triggered? call timer
+ if timer and os.mclock() - time > timeout then
+ timer(indices)
+ time = os.mclock()
+ end
- -- the other process is pending for this task?
- if coroutine.status(job_task) ~= "dead" then
+ -- append fake procs_infos for coroutine.yield()
+ procs_infos = procs_infos or {}
+ for taskid = #procs + 1, #tasks do
+ table.insert(procs_infos, {nil, taskid, 0})
+ end
- -- check
- assert(job_proc_or_errors)
+ -- wait ok
+ for _, procinfo in ipairs(procs_infos) do
+
+ -- the process info
+ local proc = procinfo[1]
+ local taskid = procinfo[2]
+ local status = procinfo[3]
- -- update the pending process
- procs[procid] = job_proc_or_errors
+ -- check
+ assert(procs[taskid] == proc)
- -- this task has been finised?
- else
+ -- resume this task
+ local job_task = tasks[taskid]
+ local ok, job_proc_or_errors = coroutine.resume(job_task, 1, status)
+ if not ok then
+ return false, job_proc_or_errors
+ end
- -- mark this task as finised
- tasks_finished[procid] = true
- end
+ -- the other process is pending for this task?
+ if coroutine.status(job_task) ~= "dead" then
+ procs[taskid] = job_proc_or_errors
+ else
+ -- mark this task as finished?
+ tasks_finished[taskid] = true
end
end
@@ -156,18 +154,26 @@ function process.runjobs(jobfunc, total, comax, timeout, timer)
local procs_pending = {}
local indices_pending = {}
for taskid, job_task in ipairs(tasks) do
- if not tasks_finished[taskid] then
+ if not tasks_finished[taskid] and procs[taskid] ~= nil then -- for coroutine.yield(proc) in os.execv
table.insert(tasks_pending, job_task)
table.insert(procs_pending, procs[taskid])
table.insert(indices_pending, indices[taskid])
end
end
+ for taskid, job_task in ipairs(tasks) do
+ if not tasks_finished[taskid] and procs[taskid] == nil then -- for coroutine.yield()
+ table.insert(tasks_pending, job_task)
+ table.insert(indices_pending, indices[taskid])
+ end
+ end
tasks = tasks_pending
procs = procs_pending
indices = indices_pending
-- produce tasks
- while #tasks < comax and index <= total do
+ tasks_pending = {}
+ indices_pending = {}
+ while (#tasks + #tasks_pending) < comax and index <= total do
-- new task
local job_task = coroutine.create(jobfunc)
@@ -180,20 +186,24 @@ function process.runjobs(jobfunc, total, comax, timeout, timer)
-- add pending tasks
if coroutine.status(job_task) ~= "dead" then
-
- -- check
- assert(job_proc_or_errors)
-
- -- put task and proc to the pendings tasks
- table.insert(tasks, job_task)
- table.insert(procs, job_proc_or_errors)
- table.insert(indices, index)
+ if job_proc_or_errors ~= nil then -- for coroutine.yield(proc) in os.execv
+ table.insert(tasks, job_task)
+ table.insert(procs, job_proc_or_errors)
+ table.insert(indices, index)
+ else
+ table.insert(tasks_pending, job_task)
+ table.insert(indices_pending, index)
+ end
end
-- next index
index = index + 1
end
+ -- append pending tasks without process
+ table.join2(tasks, tasks_pending)
+ table.join2(indices, indices_pending)
+
until #tasks == 0
-- ok