MantisBT - CMake
View Issue Details
0013106CMakeCMakepublic2012-04-06 05:032013-01-09 14:05
tfischer 
David Cole 
normalminorrandom
closedno change required 
Gentoo LinuxLinux
CMake 2.8.6 
CMake 2.8.10CMake 2.8.10 
0013106: SystemTools::CopyFileAlways fails at random due to invalid kwsys_ios::ifstream fin
I am using a custom cmake script to determine the SVN revision number of my source code during build time and to write this version number into a file "version.h" so that the compiler can include the version string into the compiled code.
The script works as follows: First, it determines the SVN revision (svnversion or environment variable) and writes a small header file called version.h.tmp. To avoid unnecessary recompilations, cmake's copy_if_different is used to copy version.h.tmp to version.h only if the SVN revision (therefore the file's content) has changed.

When testing the script, in irregular intervals the copy_if_different call fails with error message:
Error copying file (if different) from "/home/tf/programming/gna/qtcreator-build/src/parts/version.h.tmp" to "/home/tf/programming/gna/qtcreator-build/src/parts/version.h".
I added print statements before each "return false" statement in SystemTools::CopyFileAlways (eventually called by copy_if_different) to check which test fails. As it turns out, the test for !fin fails in line 1849 (for CMake 2.8.6).

The problem now is, that this failure does not follow any pattern as far as I can see. Running my custom script (attached to this report) 20 times in a loop (bash for-loop), the following output is generated.

-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
kwsys_ios::ifstream fin is NULL
Error copying file (if different) from "/home/tf/programming/gna/qtcreator-build/src/parts/version.h.tmp" to "/home/tf/programming/gna/qtcreator-build/src/parts/version.h".
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
kwsys_ios::ifstream fin is NULL
Error copying file (if different) from "/home/tf/programming/gna/qtcreator-build/src/parts/version.h.tmp" to "/home/tf/programming/gna/qtcreator-build/src/parts/version.h".
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
-- SVN version was set outside through environment variable SVN_REV
-- SVN version is AAA
kwsys_ios::ifstream fin is NULL
Error copying file (if different) from "/home/tf/programming/gna/qtcreator-build/src/parts/version.h.tmp" to "/home/tf/programming/gna/qtcreator-build/src/parts/version.h".

The for-loop to call this script is:
for n in {1..20} ; do /usr/bin/cmake -DSOURCE_DIR=/home/tf/programming/gna/proj/src/parts -DBINARY_DIR=/home/tf/programming/gna/qtcreator-build/src/parts -P /home/tf/programming/gna/proj/src/getsvn.cmake ; done

Any ideas what could cause this behaviour? How to debug/trace this problem?
No tags attached.
? getsvn.cmake (2,630) 2012-04-06 05:03
https://public.kitware.com/Bug/file/4289/getsvn.cmake
? race.cmake (815) 2012-08-22 16:11
https://public.kitware.com/Bug/file/4432/race.cmake
Issue History
2012-04-06 05:03tfischerNew Issue
2012-04-06 05:03tfischerFile Added: getsvn.cmake
2012-08-11 21:35David ColeStatusnew => backlog
2012-08-11 21:35David ColeNote Added: 0030389
2012-08-22 16:11tfischerNote Added: 0030738
2012-08-22 16:11tfischerFile Added: race.cmake
2012-08-22 16:27David ColeAssigned To => David Cole
2012-08-22 16:27David ColeStatusbacklog => assigned
2012-08-22 16:32David ColeNote Added: 0030741
2012-08-22 16:32David ColeStatusassigned => resolved
2012-08-22 16:32David ColeFixed in Version => CMake 2.8.10
2012-08-22 16:32David ColeResolutionopen => no change required
2012-08-22 16:32David ColeTarget Version => CMake 2.8.10
2013-01-09 14:05Robert MaynardNote Added: 0032079
2013-01-09 14:05Robert MaynardStatusresolved => closed

Notes
(0030389)
David Cole   
2012-08-11 21:35   
Sending old, never assigned issues to the backlog.

(The age of the bug, plus the fact that it's never been assigned to anyone means that nobody is actively working on it...)

If an issue you care about is sent to the backlog when you feel it should have been addressed in a different manner, please bring it up on the CMake mailing list for discussion. Sign up for the mailing list here, if you're not already on it: http://www.cmake.org/mailman/listinfo/cmake [^]

It's easy to re-activate a bug here if you can find a CMake developer who has the bandwidth to take it on, and ferry a fix through to our 'next' branch for dashboard testing.
(0030738)
tfischer   
2012-08-22 16:11   
I was able to trace this problem further. It seems that it makes a difference if "copy_if_different" and "remove" are executed in the same "execute_process" or in two different "execute_process" statements.
I haven't checked that in the sources, but my guess would be that the two command statements inside the execute_process statement are executed in parallel (resulting in a race condition as observed) contrary to the documentation which states "Runs the given sequence of one or more commands ..." (emphasis on "sequence", i.e. sequential, which is not parallel).

Please have a look on the attached example script and try to confirm my observation.
(0030741)
David Cole   
2012-08-22 16:32   
You are observing behavior that is by design. Sorry nobody took a closer look at this issue and got back to you before now.

The documentation for execute_process clearly states "Runs the given sequence of one or more commands with the standard output of each process piped to the standard input of the next."

The standard output of cmd1 is *PIPED* into the stdin of cmd2, so of course they're both going to be running at the same time.

It's as if you did this in a command prompt:

  cmake -E copy_if_different f1 f2 | cmake -E remove f1

You are probably thinking that it's as if you used "&&" instead of "|" in the command prompt...

So... your solution is easy. Please use two separate execute_process commands.

Perhaps the documentation should be rephrased to avoid the word sequence, since the commands will run simultaneously as they produce and consume output/input. But other than using the word "sequence" in the documentation, there's no issue here. This is behaving the way it is intended.
(0032079)
Robert Maynard   
2013-01-09 14:05   
Closing resolved issues that have not been updated in more than 4 months.