We have been seeing a few deadlock in taskWaitCheck. E.g.
Traceback (most recent call last): File "/usr/lib/python3.6/site-packages/kojihub/kojixmlrpc.py", line 266, in _wrap_handler response = handler(environ) File "/usr/lib/python3.6/site-packages/kojihub/kojixmlrpc.py", line 293, in handle_rpc return self._dispatch(method, params) File "/usr/lib/python3.6/site-packages/kojihub/kojixmlrpc.py", line 330, in _dispatch ret = koji.util.call_with_argcheck(func, params, opts) File "/usr/lib/python3.6/site-packages/koji/util.py", line 271, in call_with_argcheck return func(*args, **kwargs) File "/usr/lib/python3.6/site-packages/kojihub/kojihub.py", line 14789, in getHostTasks return host.getHostTasks() File "/usr/lib/python3.6/site-packages/kojihub/kojihub.py", line 14627, in getHostTasks finished, _ = self.taskWaitCheck(id) File "/usr/lib/python3.6/site-packages/kojihub/kojihub.py", line 14559, in taskWaitCheck result = query.execute() File "/usr/lib/python3.6/site-packages/kojihub/db.py", line 807, in execute data = _multiRow(query, self.values, (self.aliases or self.columns)) File "/usr/lib/python3.6/site-packages/kojihub/db.py", line 277, in _multiRow return [dict(zip(fields, row)) for row in _fetchMulti(query, values)] File "/usr/lib/python3.6/site-packages/kojihub/db.py", line 230, in _fetchMulti c.execute(query, values) File "/usr/lib/python3.6/site-packages/kojihub/db.py", line 148, in execute ret = self.cursor.execute(operation, parameters) psycopg2.extensions.TransactionRollbackError: deadlock detected DETAIL: Process 1583760 waits for ShareLock on transaction 1399002973; blocked by process 1586598. Process 1586598 waits for ShareLock on transaction 1399003055; blocked by process 1583760. HINT: See server log for query details. CONTEXT: while locking tuple (9777714,5) in relation "task"
It appears to be triggered by interaction with the scheduler
Metadata Update from @tkopecek: - Custom field Size adjusted to None - Issue set to the milestone: 1.34.1 - Issue tagged with: testing-ready
PR #4056
I spent some time trying to replicate this under controlled conditions and so far have not been able do, despite that fact that it happens in our instance a few times per day.
Here is what I do know about it though:
ONE. The tracebacks are always in either host.taskWait or host.getHostTasks calls.
host.taskWait
host.getHostTasks
TWO. In both types of tracebacks, we're failing in taskWaitCheck()
taskWaitCheck()
THREE. The other side of the deadlock is happening in Task.verifyHost. We know this because of the db logs. E.g.
Task.verifyHost
Process 3815840 waits for ShareLock on transaction 1649461470; blocked by process 3818796. Process 3818796: SELECT id, state FROM task WHERE (awaited IS TRUE) AND (parent=60222253) FOR UPDATE Process 3815840: SELECT host_id, state FROM task WHERE (id=60222321) FOR UPDATE
The latter query can only be coming from Task.verifyHost.
FOUR. Task.verifyHost can be called many different ways. E.g. most host calls hit it via assertHost. However, based on the timing of errors I've looked at, I'm pretty sure the other side of the deadlock is the scheduler assigning a task.
assertHost
Case in point, I observed a build task failing on this error just after creating its buildArch subtasks. None of them had started yet. So, really the only activity that could have conflicted is assignment by the scheduler. Scheduler logs for the assignments seem to line up with the task failure time.
The scheduler can assign any number of tasks in a given run. It does follow a predictable order, but that likely not the same order that taskWaitCheck is locking.
So it seems like I should be able to replicate this locally, but I so far have not been able to.
I've tried replicating it as well, with no luck so far.
Ok, I was able to replicate this with a bit of tweaking.
This branch has the adjustments: https://pagure.io/fork/mikem/koji/commits/replicate-wait-deadlock
My approach did not use actual kojid or kojihub, but simulated all activity with fakehub against my local test db.
fakehub
First, make the tasks
devtools/fakehub -u mikem -o LogLevel=WARNING --pdb makeTask sleep '[5]' devtools/fakehub -x -u builder-01 -o LogLevel=WARNING host.openTask 13924 devtools/fakehub -u mikem -o LogLevel=WARNING --pdb makeTask sleep '[5]' parent=13924 devtools/fakehub -u mikem -o LogLevel=WARNING --pdb makeTask sleep '[5]' parent=13924 ... ...make several subtasks to increase the chances (I made 10)...
Mark the subtasks awaited
devtools/fakehub -x -u builder-01 host.taskSetWait 13924 '[13925, 13926, 13927, 13928, 13929, 13930, 13931, 13932, 13933,13934,]'
Make sure the hosts show as ready
devtools/fakehub -x -u builder-01 -o LogLevel=WARNING host.updateHost 0 True devtools/fakehub -x -u builder-02 -o LogLevel=WARNING host.updateHost 0 True
Trigger the scheduler in a loop without commit
while devtools/fakehub -o RunInterval=0 -o LogLevel=INFO --no-commit -x -u builder-02 host.getLoadData; do echo; done
In parallel, have the builder check for tasks without commit
while ./devtools/fakehub --no-commit -x -u builder-01 host.getHostTasks; do echo ; done
On my machine, this generally hits the deadlock within a few repetitions.
If I merge #4056 on top of this, the error disappears.
This replication setup keeps the scheduler in a constant state of trying to assign a bunch of subtasks. Note that because no actual builder is actually running, the scheduler will eventually start ignoring them due to the ReadyTimeout setting, so if testing goes on a while, you may need to rerun those host.updateHost calls or override ReadyTimeout for the host.getLoadData call.
host.updateHost
host.getLoadData
Is there a way to incorporate the fakehub changes into the regular hub/builder? Even in a temporary side branch would be fine. We do not use the fakehub utility in QE env and I'm not sure if I would be able to create a test case without it.
Metadata Update from @tkopecek: - Issue untagged with: testing-ready - Issue tagged with: no_qe
Commit df86feab relates to this ticket
Metadata Update from @tkopecek: - Issue close_status updated to: Fixed - Issue status updated to: Closed (was: Open)
This issue has been migrated to Fedora Forge: https://forge.fedoraproject.org/koji/koji/issues/4057
Please continue any further discussion there.