Skip to content
Snippets Groups Projects
Commit ab7f9fe8 authored by Radovan Červený's avatar Radovan Červený
Browse files

fixed very sneaky FD_CLOEXEC behavior

parent 9740259f
No related branches found
No related tags found
1 merge request!15BP_cervera3 - automatic measurements, processing
...@@ -116,126 +116,106 @@ MPRPipelineResults MeasurementProvisioner::runPipeline ( const MPPipeline & pipe ...@@ -116,126 +116,106 @@ MPRPipelineResults MeasurementProvisioner::runPipeline ( const MPPipeline & pipe
   
MPRPipelineResults pipelineResults { }; MPRPipelineResults pipelineResults { };
   
try { auto fdCleanupLambda = [&] ( ) {
// close tmp files, which results in their deletion
for ( MPPipeline::const_iterator mppcIter = pipeline.cbegin ( ); mppcIter != pipeline.cend ( ); ++mppcIter ) { if ( measurementsFd != measurementsTmpfileFd )
if ( mppcIter == pipeline.cbegin ( ) ) { close ( measurementsFd );
dup ( inputTmpfileFd );
dup ( outputTmpfileFd ); MPUtils::closeShmFile ( measurementsTmpfile.second );
dup ( errorTmpfileFd ); MPUtils::closeShmFile ( inputTmpfile.second );
} else { MPUtils::closeShmFile ( outputTmpfile.second );
// swap stdin and stdout for next command MPUtils::closeShmFile ( errorTmpfile.second );
close ( 0 );
close ( 1 ); // restore our main stdin, stdout, stderr
dup ( outputTmpfileFd ); close ( 0 );
dup ( inputTmpfileFd ); close ( 1 );
close ( 2 );
// rewind previous stdout to the beginning, so the next command can read the whole file as input
lseek ( 0, 0, SEEK_SET ); dup ( curStdinFd );
dup ( curStdoutFd );
// destroy the contents of previous stdin and rewind to the beginning dup ( curStderrFd );
lseek ( 1, 0, SEEK_SET );
ftruncate ( 1, 0 ); close ( curStdinFd );
} close ( curStdoutFd );
close ( curStderrFd );
string command = mppcIter->substitute ( substitutionMap ); };
ofdlog << "| \t" << mppcIter->getRawCommand ( ) << flush;
   
try {
   
// leave the execution to the system shell for ( MPPipeline::const_iterator mppcIter = pipeline.cbegin ( ); mppcIter != pipeline.cend ( ); ++mppcIter ) {
int status = system ( command.c_str ( ) ); if ( mppcIter == pipeline.cbegin ( ) ) {
dup ( inputTmpfileFd );
dup ( outputTmpfileFd );
dup ( errorTmpfileFd );
} else {
// swap stdin and stdout for next command
close ( 0 );
close ( 1 );
dup ( outputTmpfileFd );
dup ( inputTmpfileFd );
   
if ( WEXITSTATUS ( status ) != 0 ) { // rewind previous stdout to the beginning, so the next command can read the whole file as input
// rewind stderr to read the error message lseek ( 0, 0, SEEK_SET );
lseek ( 2, 0, SEEK_SET );
ifdstream errfds ( 2 );
   
// read the whole stderr // destroy the contents of previous stdin and rewind to the beginning
stringstream buffer; lseek ( 1, 0, SEEK_SET );
buffer << errfds.rdbuf ( ); ftruncate ( 1, 0 );
}
   
pipelineResults.pipelineStatus.exitCode = WEXITSTATUS ( status ); string command = mppcIter->substitute ( substitutionMap );
pipelineResults.pipelineStatus.errorOrigin = mppcIter->getRawCommand ( );
pipelineResults.pipelineStatus.errorValue = buffer.str ( );
   
// destroy stderr contents ofdlog << "| \t" << mppcIter->getRawCommand ( ) << flush;
lseek ( 2, 0, SEEK_SET );
ftruncate ( 2, 0 );
   
ofdlog << " ERROR!" << endl; // leave the execution to the system shell
break; int status = system ( command.c_str ( ) );
}
   
if ( WEXITSTATUS ( status ) != 0 ) {
// rewind stderr to read the error message
lseek ( 2, 0, SEEK_SET );
ifdstream errfds ( 2 );
   
if ( mppcIter->getMeasure ( ) ) { // read the whole stderr
// since we are at the end of file after the output, we need to rewind stringstream buffer;
lseek ( measurementsFd, 0, SEEK_SET ); buffer << errfds.rdbuf ( );
   
ifdstream ifd ( measurementsFd ); pipelineResults.pipelineStatus.exitCode = WEXITSTATUS ( status );
pipelineResults.pipelineStatus.errorOrigin = mppcIter->getRawCommand ( );
pipelineResults.pipelineStatus.errorValue = buffer.str ( );
   
deque < sax::Token > tokens; // destroy stderr contents
sax::SaxParseInterface::parseStream ( ifd, tokens ); lseek ( 2, 0, SEEK_SET );
ftruncate ( 2, 0 );
   
measurements::MeasurementResults measurementResults = measurements::MeasurementResultsXml::parse ( tokens ); ofdlog << " ERROR!" << endl;
break;
}
   
pipelineResults.commandResults.push_back ( { mppcIter->getRawCommand ( ), std::move ( measurementResults ) } ); if ( mppcIter->getMeasure ( ) ) {
// since we are at the end of file after the output, we need to rewind
lseek ( measurementsFd, 0, SEEK_SET );
   
// destroy the contents and rewind for another commands measurements ifdstream ifd ( measurementsFd );
lseek ( measurementsFd, 0, SEEK_SET );
ftruncate ( measurementsFd, 0 );
}
ofdlog << " OK!" << endl;
}
   
} catch(::exception::CommonException & ce) { deque < sax::Token > tokens;
// close tmp files, which results in their deletion sax::SaxParseInterface::parseStream ( ifd, tokens );
if ( measurementsFd != measurementsTmpfileFd )
close ( measurementsFd );
   
//MPUtils::closeShmFile ( measurementsTmpfile.second ); measurements::MeasurementResults measurementResults = measurements::MeasurementResultsXml::parse ( tokens );
//MPUtils::closeShmFile ( inputTmpfile.second );
//MPUtils::closeShmFile ( outputTmpfile.second );
//MPUtils::closeShmFile ( errorTmpfile.second );
   
// restore our main stdin, stdout, stderr pipelineResults.commandResults.push_back ( { mppcIter->getRawCommand ( ), std::move ( measurementResults ) } );
close ( 0 );
close ( 1 );
close ( 2 );
   
dup ( curStdinFd ); // destroy the contents and rewind for another commands measurements
dup ( curStdoutFd ); lseek ( measurementsFd, 0, SEEK_SET );
dup ( curStderrFd ); ftruncate ( measurementsFd, 0 );
}
close ( curStdinFd );
close ( curStdoutFd );
close ( curStderrFd );
   
ofdlog << " OK!" << endl;
}
} catch ( ::exception::CommonException & ce ) {
fdCleanupLambda ( );
throw ce; throw ce;
} }
   
// close tmp files, which results in their deletion fdCleanupLambda ( );
if ( measurementsFd != measurementsTmpfileFd )
close ( measurementsFd );
MPUtils::closeShmFile ( measurementsTmpfile.second );
MPUtils::closeShmFile ( inputTmpfile.second );
MPUtils::closeShmFile ( outputTmpfile.second );
MPUtils::closeShmFile ( errorTmpfile.second );
// restore our main stdin, stdout, stderr
close ( 0 );
close ( 1 );
close ( 2 );
dup ( curStdinFd );
dup ( curStdoutFd );
dup ( curStderrFd );
close ( curStdinFd );
close ( curStdoutFd );
close ( curStderrFd );
   
return pipelineResults; return pipelineResults;
} }
......
...@@ -47,6 +47,11 @@ MPUtils::ShmFileHandle MPUtils::openShmFile ( ) { ...@@ -47,6 +47,11 @@ MPUtils::ShmFileHandle MPUtils::openShmFile ( ) {
if ( shmFd == -1 ) if ( shmFd == -1 )
throw::exception::CommonException ( "MPUtils: shm_open failed" ); throw::exception::CommonException ( "MPUtils: shm_open failed" );
   
// turn off FD_CLOEXEC, so it survives call to system() (exec())
int fl = fcntl ( shmFd, F_GETFD );
fl &= ~FD_CLOEXEC;
fcntl ( shmFd, F_SETFD, fl );
filename = "/dev/shm" + filename; filename = "/dev/shm" + filename;
   
if ( access ( filename.c_str ( ), F_OK ) == -1 ) { if ( access ( filename.c_str ( ), F_OK ) == -1 ) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment