Problem 1157 - No error checking for 'system' call in G4RunManager::SetRandomNumberStoreDir
Summary: No error checking for 'system' call in G4RunManager::SetRandomNumberStoreDir
Status: RESOLVED FIXED
Alias: None
Product: Geant4
Classification: Unclassified
Component: run (show other problems)
Version: other
Hardware: Other All
: P5 normal
Assignee: asai
URL:
Depends on:
Blocks:
 
Reported: 2011-01-04 09:43 CET by mmarino
Modified: 2011-01-23 21:06 CET (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this problem.
Description mmarino 2011-01-04 09:43:17 CET
When compiling on newer versions of gcc (in particular, Ubuntu/Linaro, gcc 4.4.4) with -Wall, I receive the following warning when including G4RunManager:

/home/mgmarino/software/geant4/include/geant4/G4RunManager.hh: In member function ‘void G4RunManager::SetRandomNumberStoreDir(const G4String&)’:
/home/mgmarino/software/geant4/include/geant4/G4RunManager.hh:358: warning: ignoring return value of ‘int system(const char*)’, declared with attribute warn_unused_result

The relevant code:

346     inline void SetRandomNumberStoreDir(const G4String& dir)
347     {
348       G4String dirStr = dir;
349       if( dirStr(dirStr.length()-1) != '/' ) dirStr += "/";
350 #ifndef WIN32
351       G4String shellCmd = "mkdir -p ";
352 #else
353       std::replace(dirStr.begin(), dirStr.end(),'/','\\');
354       G4String shellCmd = "mkdir ";
355 #endif
356       shellCmd += dirStr;
357       randomNumberStatusDir = dirStr;
358       system(shellCmd);
359     }


This warning is in principle valid on all systems.

When the directory is set, it is passed to a forked shell via the system command.  However, the return of the system command is not checked to ensure that the forking and the mkdir command have completed successfully.  This could introduce issues when users request directories for which they do not have the correct permissions or when some other unforeseen failure occurs, as the SetRandomNumberStoreDir function assumes that the system call has succeeded.

I think there are two possible solutions to this, I'm afraid neither is completely simple given portability issues:

1.  Check the return value of system.  This is complicated due to the fact that the return value is platform dependent and needs to be handled to determine if the error came from the forking or from the 'mkdir' call.

2.  Use POSIX and Windows 'mkdir' and 'CreateDirectory' functions directly.  This would be my suggested method since it avoids the system call altogether.  However, the recursive generation of directories would need to be handled manually.  

Both solutions would also notify the user if the call has failed and output any available system error (strerror?).  Only successful calls would result in randomNumberStatusDir being set.
Comment 1 asai 2011-01-04 18:34:18 CET
Thank you for addressing this.
We will look into the potential solution.
Comment 2 asai 2011-01-23 03:45:34 CET
Thank you once again for pointing this out.
We modify the line 354 to
    G4String shellCmd = "if not exist " + dirStr + " mkdir ";
which should fix the problem. We will release this fix with the next patch.
Comment 3 mmarino 2011-01-23 21:06:24 CET
Thanks for having a look at this.  I'm afraid this fix won't take care of the warning message or check whether the call to 'system' failed.  That is, the return value of 'system' (line 358) should be checked to ensure that it has in fact succeeded.  It is still possible for the call to fail if the directory does not exist but the user doesn't have the correct permissions for the directory.  

In our code, we have the following to check, but we only run on linux and mac os x:

       int system_return = system(pscommand);
       if ( system_return == -1 || system_return > 0 ) {
         // ps return 0 if success, system could return -1 or 127 on POSIX systems on failure.
         std::cout << "Error calling ps to determine memory usage information." << std::endl;
         std::cout << "  Return value: " << system_return << std::endl;
       }

The difficulty is that for further os support, the return value of system is platform and os dependent:

http://www.cplusplus.com/reference/clibrary/cstdlib/system/