View Issue Details Jump to Notes ] Print ]
IDProjectCategoryView StatusDate SubmittedLast Update
0013040CMakeCMakepublic2012-03-14 06:222012-09-03 16:02
ReporterAndreas Mohr 
Assigned ToBrad King 
PriorityhighSeveritycrashReproducibilityalways
StatusclosedResolutionfixed 
PlatformLinuxOS RHELOS Version5
Product VersionCMake 2.8.6 
Target VersionCMake 2.8.8Fixed in VersionCMake 2.8.8 
Summary0013040: CMakeCache.txt gets killed (zeroed, deleted, data loss data corruption) on out of disk space situation
DescriptionCMake 2.8.6.20111108-g92e65 (sorry, did not try trunk)

Steps To ReproduceA simple
dd if=/dev/zero of=cmake_binary_tree_partition/kill_space_zero.dat bs=1048576 count=3131232134
to ensure an unusable HDD will result in a CMake configure run
stomping out its CMakeCache.txt, thereby losing all configuration information,
making a very nice "cmake ." (to re-trigger successful configuration runs *)) in the _binary tree_ impossible subsequently.

*) e.g. EVEN IN AN OTHERWISE COMPLETELY EMPTY NEWLY RE-LOCATED BUILD TREE! :))


$ ls -l CMakeCache.txt
-rw-rw-r-- 1 amoh amoh 0 Mar 14 10:40 CMakeCache.txt
Additional InformationIt's considered best practice (some people would say minimum practice) to first write datasets into _temporary_ files before atomically moving them to the final location after fully successful completion, to avoid exactly the scenario that appears to be taking place here, namely an important pre-existing file being killed by the name-overwriting file having unsuccessfully attempted to gather storage space.


My (admittedly not fully satisfying) workaround against such data loss is this:

# Implement a check for minimum disk space requirement,
# and error out fatally if it's not covered.
# While a full build with limited disk space will not be successful,
# an even worse problem is that CMake will corrupt a newly written
# CMakeCache.txt when running out of space...
function(detect_build_space_less_than_mb _mb_size _sufficient_space_bool_out)
  set(sufficient_space_bool_ true) # be optimistic :)
  if(UNIX)
    # http://stackoverflow.com/questions/8110530/check-disk-space-for-current-directory-in-bash [^]
    find_program(stat_BIN stat)
    if(stat_BIN)
      execute_process(COMMAND "${stat_BIN}" -f --format=%a:%S "${CMAKE_BINARY_DIR}"
        OUTPUT_VARIABLE stat_stdout_
      )
      string(REGEX REPLACE "^(.*):.*$" "\\1" stat_block_count_ "${stat_stdout_}")
      string(REGEX REPLACE "^.*:(.*)$" "\\1" stat_block_size_ "${stat_stdout_}")
      math(EXPR megabytes_remaining_ "(${stat_block_count_}*${stat_block_size_})/(1024*1024)")
      #message(FATAL_ERROR "stat_stdout_ ${stat_stdout_}, stat_block_count_ ${stat_block_count_} stat_block_size_ ${stat_block_size_}, megabytes_remaining_ ${megabytes_remaining_}")
      if("${megabytes_remaining_}" LESS "${_mb_size}")
        set(sufficient_space_bool_ false)
      endif("${megabytes_remaining_}" LESS "${_mb_size}")
    else(stat_BIN)
      message(FATAL_ERROR "could not find stat binary! Please extend this code to cope with this situation in a better way, if possible.")
    endif(stat_BIN)
  endif(UNIX)
  set(${_sufficient_space_bool_out} ${sufficient_space_bool_} PARENT_SCOPE)
endfunction(detect_build_space_less_than_mb _mb_size _sufficient_space_bool_out)

function(check_sufficient_free_build_space)
  set(MASTER_BUILD_MINIMUM_SPACE_IN_MEGABYTES 500 CACHE STRING "Minimum free space (in MB) to require for a successful build (specify 0 to disable check)")
  if(MASTER_BUILD_MINIMUM_SPACE_IN_MEGABYTES GREATER 0)
    detect_build_space_less_than_mb(${MASTER_BUILD_MINIMUM_SPACE_IN_MEGABYTES} have_sufficient_space_)
    if(NOT have_sufficient_space_)
      message( "There's not enough free space to guarantee a successful build! (requested: ${MASTER_BUILD_MINIMUM_SPACE_IN_MEGABYTES}MB)")
    endif(NOT have_sufficient_space_)
  endif(MASTER_BUILD_MINIMUM_SPACE_IN_MEGABYTES GREATER 0)
endfunction(check_sufficient_free_build_space)

check_sufficient_free_build_space()


# ...and add a default target to create a backup of CMakeCache.txt,
# since that file might get destroyed too easily (at least CMake 2.6.4
# will kill it on out-of-disk-space, resulting in complete abort of
# configuration run):
if(NOT TARGET master_backup_CMakeCache)
  # Better reference specific CMAKE_CACHEFILE_DIR variable (same as CMAKE_BINARY_DIR).
  # Unfortunately there's no CMake file name variable for "CMakeCache.txt"
  # (source code of CMake always open-codes that name),
  # thus there's nothing to reference here.
  set(CMakeCache_file "${CMAKE_CACHEFILE_DIR}/CMakeCache.txt")
  set(CMakeCache_file_backup "${CMakeCache_file}.backup")
  add_custom_command(OUTPUT "${CMakeCache_file_backup}"
    # copy_if_different _not_ needed (target dependency needs remaking? --> _do_ copy!)
    COMMAND "${CMAKE_COMMAND}" -E copy "${CMakeCache_file}" "${CMakeCache_file_backup}"
    COMMENT "creating CMakeCache backup (${CMakeCache_file_backup})"
  )
  add_custom_target(master_backup_CMakeCache ALL DEPENDS "${CMakeCache_file_backup}")
endif(NOT TARGET master_backup_CMakeCache)


Severity "crash" since it will render a working build irreversibly non-working.


Thanks!
TagsNo tags attached.
Attached Files

 Relationships

  Notes
(0028915)
Brad King (manager)
2012-03-14 08:30

Wow, that's a pretty old bug. Most of CMake's generation uses temporary files followed by atomic renames for replacement but this one predates that convention. Fixed:

  http://cmake.org/gitweb?p=cmake.git;a=commitdiff;h=9eb8e4b2 [^]
(0030886)
David Cole (manager)
2012-09-03 16:02

Closing resolved issues that have not been updated in more than 4 months.

 Issue History
Date Modified Username Field Change
2012-03-14 06:22 Andreas Mohr New Issue
2012-03-14 08:30 Brad King Note Added: 0028915
2012-03-14 08:30 Brad King Status new => resolved
2012-03-14 08:30 Brad King Fixed in Version => CMake 2.8.8
2012-03-14 08:30 Brad King Resolution open => fixed
2012-03-14 08:30 Brad King Assigned To => Brad King
2012-04-19 15:53 David Cole Target Version => CMake 2.8.8
2012-09-03 16:02 David Cole Note Added: 0030886
2012-09-03 16:02 David Cole Status resolved => closed


Copyright © 2000 - 2018 MantisBT Team