Skip to content

[19.0] [FIX] queue_job: deadlock when the on fail hook writes the job's records - #1001

Merged
OCA-git-bot merged 1 commit into
OCA:19.0from
camptocamp:19.0-fix-queue_job-on_fail-deadlock
Oct 5, 2026
Merged

OCA-git-bot merged 1 commit into
OCA:19.0from
camptocamp:19.0-fix-queue_job-on_fail-deadlock

Conversation

@ivantodorovich

Copy link
Copy Markdown
Contributor

When a job fails, _runjob records the failure and calls the on_fail hook from a temporary cursor, while the job's own transaction is still open.

If the hook writes on a record the job wrote, it waits for the job's lock, which is only released after the hook. The job stays started forever -> deadlock


This PR runs the job inside a savepoint: when the job fails, rolling back the savepoint releases the locks it took. The job lock on queue_job_lock was taken before the savepoint, so it stays held.

@OCA-git-bot

Copy link
Copy Markdown
Contributor

Hi @guewen, @sbidoul,
some modules you are maintaining are being modified, check this out!

@simahawk simahawk left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG

Comment thread queue_job/controllers/main.py Outdated
Comment thread queue_job/controllers/main.py Outdated
@ivantodorovich
ivantodorovich force-pushed the 19.0-fix-queue_job-on_fail-deadlock branch from d33125d to c51fe59 Compare September 30, 2026 13:57

@grindtildeath grindtildeath left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice 👌

@UsmanGhias UsmanGhias left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clean patch for OCA/queue.

Observations:

  • SQL query correctly uses parameterized %s arguments for cr.execute, maintaining clean injection safety.

Ready for testing on standard environments.

Regards,
Usman
https://usmanghias.co.uk

@UsmanGhias UsmanGhias left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great work on this PR! Fixing this deadlock scenario is a massive win for high-concurrency Odoo environments running heavy background queues.

Technically, wrapping the execution block inside env.cr.savepoint() is a clean way to drop row-level locks on failure while safely preserving the session-level advisory locks via queue_job_lock. I also appreciate how you structured the regression test using a separate cursor and a lock timeout to properly simulate the multi-connection concurrency issue without flakiness.

Just a small heads-up on the truncated test code at the end of the patch, but the logic itself is rock-solid. Excited to see this land in version 19!

Regards,
Usman
https://usmanghias.co.uk

@OCA-git-bot

Copy link
Copy Markdown
Contributor

This PR has the approved label and has been created more than 5 days ago. It should therefore be ready to merge by a maintainer (or a PSC member if the concerned addon has no declared maintainer). 🤖

@ivantodorovich

Copy link
Copy Markdown
Contributor Author

can we merge? 🙏🏻

Comment thread queue_job/controllers/main.py Outdated
# On failure, rolling back the savepoint releases the locks taken
# by the job: the failure is handled from another cursor, which
# may write on the same records (e.g. the on fail hook).
# NOTE: Session-level advisory locks are not released by the rollback.

@guewen guewen Oct 5, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the point of this comment @ivantodorovich @simahawk?
There is no advisory lock involved (and if it did it would probably not be a session-level one)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it may be the result of a confusion.

The session-level advisory lock in this module is only used to elect the active jobrunner, but it has absolutely nothing to do with the actual execution of a job (this code).

The locks that I'm trying to release on failure are, in fact, the related business record's table rows locks (the records the job is actually updating). e.g: the exchange_record table rows, for example if using the edi-framework

@guewen guewen Oct 5, 2026 •

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The session-level advisory lock in this module is only used to elect the active jobrunner, but it has absolutely nothing to do with the actual execution of a job (this code).

Exactly!

Would you mind removing the line to prevent further confusion please? Then I'm fine with merging

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! I also slightly reworded the comment above, in an effort to make it clearer
https://github.com/OCA/queue/compare/c51fe59867fc9620523fe459e20bb8aa3fc63156..3881714352f24644a50126c01127a8a2ad678951

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

The failure is handled from a temporary cursor while the failed job's
transaction still holds its locks: an on fail hook writing on the same
records waited forever. Perform the job in a savepoint so that its
locks are released when it fails.
@ivantodorovich
ivantodorovich force-pushed the 19.0-fix-queue_job-on_fail-deadlock branch from c51fe59 to 3881714 Compare October 5, 2026 17:57
@guewen

guewen commented Oct 5, 2026

Copy link
Copy Markdown
Member

/ocabot merge patch

@OCA-git-bot

Copy link
Copy Markdown
Contributor

On my way to merge this fine PR!
Prepared branch 19.0-ocabot-merge-pr-1001-by-guewen-bump-patch, awaiting test results.

@OCA-git-bot
OCA-git-bot merged commit 4dbf51a into OCA:19.0 Oct 5, 2026
8 checks passed
@OCA-git-bot

Copy link
Copy Markdown
Contributor

Congratulations, your PR was merged at ed5d7f3. Thanks a lot for contributing to OCA. ❤️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

7 participants