Project

Profile

Help

Issue #5982

Race condition in RepositoryVersion.new_version()

Added by osapryki 9 months ago. Updated 9 months ago.

Status:
NEW
Priority:
Normal
Assignee:
-
Category:
-
Sprint/Milestone:
-
Start date:
Due date:
Estimated time:
Severity:
2. Medium
Version:
Platform Release:
OS:
Triaged:
Yes
Groomed:
No
Sprint Candidate:
No
Tags:
Sprint:
Quarter:

Description

If `RepositoryVersion.new_version` is executed at the same time in two parallel transactions, one of transactions may fail with unique constraint error:

duplicate key value violates unique constraint "pulp_app_repositoryversion_repository_id_number_07cb5788_uniq" DETAIL: Key (repository_id, number)=(1, 735) already exists.

This is caused because of race condition possible in `RepositoryVersion.new_version()` call:

SELECT last_version FROM pulp_app_repository WHERE id = 1
 last_version
--------------
          21

TRANSACTION 1       TRANSACTION 2
=============       =============
BEGIN;
-----------------------------------------------------------
                    BEGIN;
-----------------------------------------------------------
INSERT INTO pulp_app_repositoryversion
(repository_id, number) VALUES (1, 22)
# NOTE: number = int(self.last_version) + 1;
-----------------------------------------------------------
UPDATE pulp_app_repository
SET last_version = 22;
-----------------------------------------------------------
                    INSERT INTO pulp_app_repositoryversion
                    (repository_id, number) VALUES (1, 22)
                    # NOTE: number = int(self.last_version) + 1;
-----------------------------------------------------------
                    UPDATE pulp_app_repository
                    SET last_version = 22;
-----------------------------------------------------------
COMMIT;
# NOTE: OK
-----------------------------------------------------------
                    COMMIT;
                    # NOTE: uplicate key value violates unique
                    # constraint
-----------------------------------------------------------

Solution:

You should lock repository record to perform `last_version` increment and update (e.g. do SELECT FOR UPDATE before incrementing last_version counter and creating a new version).

History

#1 Updated by bmbouter 9 months ago

I want to share some info on Pulp's tasking system. Pulp's tasking system provides a serialization of tasks based on locks. In the case of new_version, e.g. it's typically called from add_and_remove here. That is dispatched with the lock on repository itself second param here which causes add_and_remove operations to be serialized.

Improving the code to have fewer race conditions sounds good though, especially if plugin writers want to create new versions in the viewset. Do plugins want to create new_version in the viewsets?

#2 Updated by fao89 9 months ago

  • Triaged changed from No to Yes

Please register to edit this issue

Also available in: Atom PDF