GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — RLock undocumented behavior in case of multiple acquire · Issue #70795 · python/cpython

RLock undocumented behavior in case of multiple acquire #70795

New issue
Copy link
New issue
Copy link
Closed
Closed
RLock undocumented behavior in case of multiple acquire#70795
Copy link
Labels
3.11only security fixesonly security fixesdocsDocumentation in the Doc dirDocumentation in the Doc direasystdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory

Description

smbrd
mannequin
opened on Mar 22, 2016
Issue body actions
BPO 26608
Nosy @MojoVampire, @iritkatriel

Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

Show more details

GitHub fields:

assignee = None
closed_at = None
created_at = <Date 2016-03-22.06:56:38.096>
labels = ['easy', '3.11', 'library', 'docs']
title = 'RLock undocumented behavior in case of multiple acquire'
updated_at = <Date 2021-06-18.14:35:22.245>
user = 'https://bugs.python.org/smbrd'

bugs.python.org fields:

activity = <Date 2021-06-18.14:35:22.245>
actor = 'iritkatriel'
assignee = 'docs@python'
closed = False
closed_date = None
closer = None
components = ['Documentation', 'Library (Lib)']
creation = <Date 2016-03-22.06:56:38.096>
creator = 'smbrd'
dependencies = []
files = []
hgrepos = ['348']
issue_num = 26608
keywords = ['easy']
message_count = 4.0
messages = ['262165', '262231', '270216', '396068']
nosy_count = 5.0
nosy_names = ['docs@python', 'josh.r', 'ahxxm', 'smbrd', 'iritkatriel']
pr_nums = []
priority = 'normal'
resolution = None
stage = None
status = 'open'
superseder = None
type = None
url = 'https://bugs.python.org/issue26608'
versions = ['Python 3.11']

Linked PRs

  • gh-70795: Rework RLock documentation #103853
  • [3.13] gh-70795: Rework RLock documentation (GH-103853) #119436
  • [3.12] gh-70795: Rework RLock documentation (GH-103853) #119437

Activity

  1. smbrd commented on Mar 22, 2016

    @smbrd
    smbrdmannequin
    on Mar 22, 2016
    MannequinAuthor
    More actions

    The number of acquisitions must be the same as the number of releases or else lock will not be released for other threads leading to deadlock. This is not mentioned in documentation.

    First acquisition returns boolean and further acquisitions return 1. This is also not mentioned in documentation.

  2. smbrd
    assigned
    docspython
    on Mar 22, 2016
  3. smbrd
    added
    docsDocumentation in the Doc dirDocumentation in the Doc dir
    stdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory
    on Mar 22, 2016
  4. MojoVampire commented on Mar 23, 2016

    @MojoVampire
    MojoVampiremannequin
    on Mar 23, 2016
    Mannequin
    More actions

    Per the docs ( https://docs.python.org/3/library/threading.html#rlock-objects ):

    "To unlock the lock, a thread calls its release() method. acquire()/release() call pairs may be nested; only the final release() (the release() of the outermost pair) resets the lock to unlocked and allows another thread blocked in acquire() to proceed."

    The docs aren't super clear on the return type, but they aren't so overly specified as to make returning either True or 1 incorrect; they use lowercase "true" to describe the return value, which doesn't *have* to mean True, just something that evaluates as truthy.

    In 3.5 at least, it looks like both initial and subsequent acquires are all returning True, even when called without passing an argument; this actually violates the docs, which claim that not passing an argument means "There is no return value" (possibly only when there is contended acquisition, the wording is odd), when in fact a no-argument call returns True just like explicitly passing blocking as True.

  5. ahxxm commented on Jul 12, 2016

    @ahxxm
    ahxxmmannequin
    on Jul 12, 2016
    Mannequin
    More actions

    As seen from commit log, all return type are double back-quoted, this could be a rendering error.

    I think this commit somehow makes it clear that RLock is a thread-level reentrant lock, some code example of suggested usage might be helpful though.

  6. iritkatriel commented on Jun 18, 2021

    @iritkatriel
    iritkatriel
    on Jun 18, 2021
    Member
    More actions

    The RLock documentation is a bit more verbose than it needs to be (for instance, there is no reason to specify the "no args" case separately from the "blocking=True" case (since True is the default value of blocking).

    The issue of balancing acquire/release calls is mentioned as Josh says, but could perhaps be stated more simply as well.

  7. iritkatriel
    added
    easy
    3.11only security fixesonly security fixes
    on Jun 18, 2021
  8. ezio-melotti
    transferred this issue fromon Apr 10, 2022
  9. samatjain commented on Apr 25, 2023

    @samatjain
    samatjain
    on Apr 25, 2023
    Contributor
    More actions

    Working on this at PyCon 2023's cpython sprint.

  10. samatjain commented on Apr 25, 2023

    @samatjain
    samatjain
    on Apr 25, 2023
    Contributor
    More actions

    Notes while trying to update the documentation:

    First acquisition returns boolean and further acquisitions return 1. This is also not mentioned in documentation.

    This longer seems to be true; acquire appears to always return True or False. Also, the documentation has a statement:

    If more than one thread is blocked waiting until the lock is unlocked, only one at a time will be able to grab ownership of the lock. There is no return value in this case.

    I have no idea what this means; why would it not return True or False? Confirmed w/ @gpshead it doesn't make sense. It's able to acquire the lock or not!

    Here's a test program I have been fiddling with on Python 3.12:

    import operator
    import time
    import threading
    
    LEVEL_LIMIT: int = 10
    THREADS_MAX = 16
    
    global_rlock = threading.RLock()
    
    
    def recursively_lock(level: int):
        """Test for RLock. Recusively call itself and observe the return value of acquire/release."""
    
        tid = threading.get_ident()
    
        if level == LEVEL_LIMIT:
            print(f"{LEVEL_LIMIT=} reached, stopping recursion")
            return
    
        print(f"Started {tid=}")
    
        rv = global_rlock.acquire(blocking=False)
        if rv:
            print(f"RLock acquire()={rv} at {level=} for {tid=}")
            time.sleep(0.1)
    
            recursively_lock(level + 1)
    
            rv = global_rlock.release()
            print(f"RLock release()={rv} at {level=}")
        else:
            print(f"Unable to acquire lock for {tid=} {rv=}")
    
    
    if __name__ == "__main__":
        threads: list[threading.Thread] = []
        for i in range(0, THREADS_MAX):
            threads.append(threading.Thread(target=recursively_lock, args=(0,)))
    
        for t in threads:
            t.start()
        # map(operator.methodcaller("start"), threads)
    
        map(operator.methodcaller("join"), threads)
        print("Hello world")

    I've been unable to replicate the case where None is returned, or acquire not returning True or False.

  11. samatjain
    added a commit that references this issue on Apr 25, 2023

    pythongh-70795: Rework RLock documentation

    16d2a21
  12. samatjain commented on Apr 25, 2023

    @samatjain
    samatjain
    on Apr 25, 2023
    Contributor
    More actions

    The old docs mention that acquire returns None, this seems not the case looking at rlock_acquire's implementation https://github.com/python/cpython/blob/main/Modules/_threadmodule.c#L355

    Double checked by gpshead

  13. AlexWaygood
    added a commit that references this issue on Apr 25, 2023

    Merge branch 'main' into pythongh-70795-RLock-docs

    42ed620
  14. CAM-Gerlach
    added 2 commits that reference this issue on May 22, 2024

    Merge branch 'main' into pythongh-70795-RLock-docs

    1c28ee7

    gh-70795: Rework RLock documentation (#103853)

    2fbea81
  15. miss-islington
    added 2 commits that reference this issue on May 22, 2024

    pythongh-70795: Rework RLock documentation (pythonGH-103853)

    267df26

    pythongh-70795: Rework RLock documentation (pythonGH-103853)

    1d9904f
  16. CAM-Gerlach
    added a commit that references this issue on May 22, 2024

    [3.12] gh-70795: Rework RLock documentation (GH-103853) (#119437)

    7eb59cd
  17. gpshead
    added a commit that references this issue on May 22, 2024

    [3.13] gh-70795: Rework RLock documentation (GH-103853) (#119436)

    a6ed742
  18. hugovk
    closed this as completedon Jun 15, 2024
  19. estyxx
    added a commit that references this issue on Jul 17, 2024

    pythongh-70795: Rework RLock documentation (python#103853)

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    3.11only security fixesonly security fixesdocsDocumentation in the Doc dirDocumentation in the Doc direasystdlibStandard Library Python modules in the Lib/ directoryStandard Library Python modules in the Lib/ directory

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions

      You are visitor 01402503 — GeezerVison does not store the pages you look up.
      Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.