Skip to content

Commit

Permalink
Prevent multiple processes from bootstrapping vcpkg simultaneously
Browse files Browse the repository at this point in the history
  • Loading branch information
vector-of-bool committed Nov 11, 2021
1 parent 806aec6 commit 7332335
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 27 deletions.
35 changes: 10 additions & 25 deletions pmm/conan.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -113,32 +113,14 @@ function(_pmm_conan_managed_ensure_installed)

# Before we continue, lock access to the virtualenv
_pmm_log(DEBUG "PMM Conan venv directory is [${_PMM_CONAN_MANAGED_VENV_DIR}]")
file(
LOCK "${_PMM_CONAN_MANAGED_VENV_DIR}" DIRECTORY
GUARD FUNCTION
TIMEOUT 3
RESULT_VARIABLE lock_res
_pmm_verbose_lock(
"${_PMM_CONAN_MANAGED_VENV_DIR}" DIRECTORY
FIRST_MESSAGE "Anohter CMake instance is installing Conan. Please wait..."
FAIL_MESSAGE "Unable to obtain the virtualenv lock. Check if there is a stuck process holding it open."
RESULT_VARIABLE did_lock
)
if(lock_res)
_pmm_log("Another CMake instance is installing Conan. Please wait...")
file(
LOCK "${_PMM_CONAN_MANAGED_VENV_DIR}" DIRECTORY
GUARD FUNCTION
TIMEOUT 60
RESULT_VARIABLE lock_res
)
if(lock_res)
_pmm_log("Unable to obtain lock after 60 seconds. We'll try for one more minute...")
file(
LOCK "${_PMM_CONAN_MANAGED_VENV_DIR}" DIRECTORY
GUARD FUNCTION
TIMEOUT 60
RESULT_VARIABLE lock_res
)
if(lock_res)
message(FATAL_ERROR "Unable to obtain exclusive lock on directory ${_PMM_CONAN_MANAGED_VENV_DIR}. Abort.")
endif()
endif()
if(NOT did_lock)
message(FATAL_ERROR "Unable to obtain exclusive lock on directory ${_PMM_CONAN_MANAGED_VENV_DIR}. Abort.")
endif()

if(NOT must_reinstall)
Expand Down Expand Up @@ -173,11 +155,13 @@ function(_pmm_conan_managed_ensure_installed)
endif()

if(NOT must_reinstall)
file(LOCK "${_PMM_CONAN_MANAGED_VENV_DIR}" DIRECTORY RELEASE)
return()
endif()

if(PMM_CONAN_MANAGED_NO_INSTALL)
# Caller has requested that we do not run an install.
file(LOCK "${_PMM_CONAN_MANAGED_VENV_DIR}" DIRECTORY RELEASE)
return()
endif()

Expand All @@ -193,6 +177,7 @@ function(_pmm_conan_managed_ensure_installed)
if(NOT PMM_CONAN_EXECUTABLE)
message(FATAL_ERROR "We failed to install Conan in a new virtualenv.")
endif()
file(LOCK "${_PMM_CONAN_MANAGED_VENV_DIR}" DIRECTORY RELEASE)
endfunction()


Expand Down
46 changes: 46 additions & 0 deletions pmm/util.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ function(_pmm_get_var_from_file filepath varname)
set(${varname} ${propt} PARENT_SCOPE)
endfunction()


function(_pmm_generate_cli_scripts force)
# The sh scipt
if(NOT EXISTS "${CMAKE_BINARY_DIR}/pmm-cli.sh" OR ${force})
Expand All @@ -148,6 +149,7 @@ function(_pmm_generate_cli_scripts force)
endif()
endfunction()


function(_pmm_generate_shim name executable)
# The sh scipt
if (NOT EXISTS "${CMAKE_BINARY_DIR}/${name}.sh")
Expand All @@ -163,3 +165,47 @@ function(_pmm_generate_shim name executable)
file(WRITE "${CMAKE_BINARY_DIR}/${name}.bat" "@echo off\n\"${executable}\" %*")
endif ()
endfunction()


function(_pmm_verbose_lock fpath)
_pmm_parse_args(
. DIRECTORY
- FIRST_MESSAGE FAIL_MESSAGE RESULT_VARIABLE
)
set(arg_dir)
if(ARG_DIRECTORY)
set(arg_dir "DIRECTORY")
endif()
set("${ARG_RESULT_VARIABLE}" TRUE PARENT_SCOPE)
file(
LOCK "${fpath}" ${arg_dir}
GUARD PROCESS
TIMEOUT 3
RESULT_VARIABLE lock_res
)
if(NOT lock_res)
return()
endif()
# Couldn't get the lock
_pmm_log("${ARG_FIRST_MESSAGE}")
file(
LOCK "${dir}" ${arg_dir}
GUARD PROCESS
TIMEOUT 60
RESULT_VARIABLE lock_res
)
if(NOT lock_res)
return()
endif()
_pmm_log("Unable to obtain lock after 60 seconds. We'll try for one more minute...")
file(
LOCK "${_PMM_CONAN_MANAGED_VENV_DIR}" ${arg_dir}
GUARD PROCESS
TIMEOUT 60
RESULT_VARIABLE lock_res
)
if(lock_res)
message(WARNING "${ARG_FAIL_MESSAGE}")
set("${ARG_RESULT_VARIABLE}" FALSE PARENT_SCOPE)
endif()
endfunction()
16 changes: 14 additions & 2 deletions pmm/vcpkg.cmake
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
# Download vcpkg at revision `rev` and place the built result in `dir`
function(_pmm_ensure_vcpkg dir rev)
_pmm_verbose_lock(
"${dir}" DIRECTORY
FIRST_MESSAGE "Another CMake instance is bootstrapping vcpkg. Please wait..."
FAIL_MESSAGE "Unable to obtain vcpkg bootstrapping lock. Check if there is a stuck process holding it open."
RESULT_VARIABLE did_lock
)
if(NOT did_lock)
message(FATAL_ERROR "Unable to obtain exclusive lock on directory ${_PMM_CONAN_MANAGED_VENV_DIR}. Abort.")
endif()
# The final executable is deterministically placed:
set(PMM_VCPKG_EXECUTABLE "${dir}/vcpkg${CMAKE_EXECUTABLE_SUFFIX}"
CACHE FILEPATH
"Path to vcpkg for this project"
FORCE
)
_pmm_log(DEBUG "Expecting vcpkg executable at ${PMM_VCPKG_EXECUTABLE}")
# Check if the given directory already exists, which means we've already
# Check if the vcpkg exe already exists, which means we've already
# bootstrapped and installed it
if(IS_DIRECTORY "${dir}")
if(EXISTS "${PMM_VCPKG_EXECUTABLE}")
file(LOCK "${dir}" DIRECTORY RELEASE)
return()
endif()
# We do the build in a temporary directory, then rename that temporary dir
Expand Down Expand Up @@ -81,6 +91,8 @@ function(_pmm_ensure_vcpkg dir rev)
_pmm_log("vcpkg successfully bootstrapped to ${dir}")
# Fix for "Could not detect vcpkg-root."
execute_process(COMMAND ${CMAKE_COMMAND} -E sleep 1)
# Release the exclusive lock on the directory we obtained at the top of this fn
file(LOCK "${dir}" DIRECTORY RELEASE)
endfunction()

function(_pmm_vcpkg_default_triplet out)
Expand Down

0 comments on commit 7332335

Please sign in to comment.