Skip to content

twister: Fix race condition in try_making_symlink #93608

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Jul 25, 2025
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 20 additions & 11 deletions scripts/pylib/twister/twisterlib/coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -518,7 +518,11 @@ def try_making_symlink(source: str, link: str):
source (str): The path to the source file.
link (str): The path where the symbolic link should be created.
"""
if os.path.exists(link):
symlink_error = None

try:
os.symlink(source, link)
except FileExistsError:
if os.path.islink(link):
if os.readlink(link) == source:
# Link is already set up
Expand All @@ -529,19 +533,24 @@ def try_making_symlink(source: str, link: str):
# File contents are the same
return

# link exists, but points to a different file, remove the link. We'll
# try to create a new one below
os.remove(link)

# Create the symlink
try:
os.symlink(source, link)
# link exists, but points to a different file. We'll create a new link
# and replace it atomically with the old one
temp_filename = f"{link}.{os.urandom(8).hex()}"
try:
os.symlink(source, temp_filename)
os.replace(temp_filename, link)
except OSError as e:
symlink_error = e
except OSError as e:
symlink_error = e

if symlink_error:
logger.error(
"Error creating symlink: %s, attempting to copy.", str(e)
"Error creating symlink: %s, attempting to copy.", str(symlink_error)
)
shutil.copy(source, link)

temp_filename = f"{link}.{os.urandom(8).hex()}"
shutil.copy(source, temp_filename)
os.replace(temp_filename, link)

def choose_gcov_tool(options, is_system_gcov):
gcov_tool = None
Expand Down
Loading