27 #include "boost/filesystem.hpp" 33 #include <sys/resource.h> 34 #include "tbb/task_arena.h" 37 #include "boost/bind.hpp" 38 #include "boost/shared_ptr.hpp" 39 #include "boost/ptr_container/ptr_deque.hpp" 74 edm::EndRunProducer> {
89 void executeScript(std::vector<std::string>
const&
args,
int id,
bool isPost)
const;
96 const std::vector<std::string>
args_;
132 scriptName_((iConfig.getParameter<
edm::FileInPath>(
"scriptName")).fullPath()),
135 npars_(iConfig.getParameter<uint32_t>(
"numberOfParameters")),
136 nEvents_(iConfig.getUntrackedParameter<uint32_t>(
"nEvents")),
142 throw cms::Exception(
"ExternalLHEProducer") <<
"Problem with configuration: " <<
args_.size() <<
" script arguments given, expected " <<
npars_;
144 if (iConfig.
exists(
"nPartonMapping")) {
146 for (
auto&
cfg : processMap) {
147 unsigned processId(
cfg.getParameter<
unsigned>(
"idprup"));
151 if (orderStr ==
"LO")
153 else if (orderStr ==
"NLO")
156 throw cms::Exception(
"ExternalLHEProducer") <<
"Invalid order specification for process " << processId <<
": " << orderStr;
158 unsigned np(
cfg.getParameter<
unsigned>(
"np"));
164 produces<LHEXMLStringProduct, edm::Transition::BeginRun>(
"LHEScriptOutput");
166 produces<LHEEventProduct>();
167 produces<LHERunInfoProduct, edm::Transition::BeginRun>();
168 produces<LHERunInfoProduct, edm::Transition::EndRun>();
190 <<
"The likely cause is that the lhe file contains fewer events than were requested, which is possible " 191 <<
"in case of phase space integration or unweighting efficiency problems.";
194 std::unique_ptr<LHEEventProduct> product(
218 order = procDef.first;
221 catch (std::out_of_range&) {
227 product->setNpLO(np);
228 product->setNpNLO(-1);
231 product->setNpLO(-1);
232 product->setNpNLO(np);
248 std::for_each(
runInfo_->getHeaders().begin(),
252 std::for_each(
runInfo_->getComments().begin(),
286 <<
"The ExternalLHEProducer module requires the RandomNumberGeneratorService\n" 287 "which is not present in the configuration file. You must add the service\n" 288 "in the configuration file if you want to run ExternalLHEProducer";
291 std::vector<std::string> infiles;
297 std::exception_ptr except;
298 std::atomic<char> exceptSet{0};
300 tbb::this_task_arena::isolate([
this, &except, &infiles, &exceptSet, nEventsAve, overflow,
seed]() {
301 tbb::empty_task* waitTask =
new (tbb::task::allocate_root()) tbb::empty_task;
306 if (
nEvents_ % nThreads_ != 0 and
t >= overflow) {
310 [
t,
this, &infiles,
seed, nEvents, &except, &exceptSet, waitTask]() {
312 using namespace boost::filesystem;
315 infiles[
t] =
out.native();
319 if (exceptSet.compare_exchange_strong(expected, 1)) {
320 except = std::current_exception();
324 waitTask->decrement_ref_count();
326 tbb::task::spawn(*
task);
328 waitTask->wait_for_all();
331 if (exceptSet != 0) {
332 std::rethrow_exception(except);
335 infiles = std::vector<std::string>(1,
outputFile_);
345 edm::LogWarning(
"ExternalLHEProducer") << postcmd[0] <<
" is not a relative path. Run it as a shell command.";
357 using namespace boost::filesystem;
362 std::ifstream instream(file);
366 instream.seekg (0, instream.end);
367 int insize = instream.tellg();
368 instream.seekg (0, instream.beg);
369 p->fillCompressedContent(instream, 0.25*insize);
377 unsigned int skip = 0;
378 reader_ = std::make_unique<lhef::LHEReader>(infiles,
skip);
385 std::for_each(
runInfo_->getHeaders().begin(),
389 std::for_each(
runInfo_->getComments().begin(),
411 std::unique_ptr<LHERunInfoProduct> product(
runInfoProducts_.pop_front().release());
418 if (std::getenv(
"VALIDATION_RUN") !=
nullptr) {
420 <<
"Event loop is over, but there are still lhe events to process, ignoring...";
423 <<
"Error in ExternalLHEProducer::endRunProduce(). " 424 <<
"Event loop is over, but there are still lhe events to process." 425 <<
"This could happen if lhe file contains more events than requested. This is never expected to happen.";
432 using namespace boost::filesystem;
435 if (unlink(
out.c_str())) {
436 throw cms::Exception(
"OutputDeleteError") <<
"Unable to delete original script output file " <<
out 437 <<
" (errno=" << errno <<
", " << strerror(errno) <<
").";
443 <<
" (errno=" << errno <<
", " << strerror(errno) <<
").";
450 std::uint32_t
seed)
const {
451 std::vector<std::string>
args;
452 args.reserve(3 +
args_.size());
454 args.push_back(
args_.front());
455 args.push_back(std::to_string(nEvents));
457 args.push_back(std::to_string(seed));
459 args.push_back(std::to_string(nThreads));
462 for (
unsigned int iArg = 0; iArg < args.size(); iArg++) {
463 LogDebug(
"LHEInputArgs") <<
"arg [" << iArg <<
"] = " << args[iArg];
479 if ((dir = opendir(
"/proc/self/fd"))) {
481 while ((dp = readdir (dir)) !=
nullptr) {
482 if ((strcmp(dp->d_name,
".") == 0) || (strcmp(dp->d_name,
"..") == 0)) {
485 if (sscanf(dp->d_name,
"%d", &fd) != 1) {
501 for (fd=3; fd<maxfd+1; fd++) {
516 int filedes[2], fd_flags;
523 if ((fd_flags = fcntl(filedes[1], F_GETFD,
NULL)) == -1) {
524 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to get pipe file descriptor flags (errno=" << rc <<
", " << strerror(rc) <<
")";
526 if (fcntl(filedes[1], F_SETFD, fd_flags | FD_CLOEXEC) == -1) {
527 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to set pipe file descriptor flags (errno=" << rc <<
", " << strerror(rc) <<
")";
530 unsigned int argc_pre = 0;
535 unsigned int argc = argc_pre + args.size();
537 char **
argv =
new char *[argc+1];
541 for (
unsigned int i = 0;
i < args.size();
i++) {
542 argv[argc_pre +
i] = strdup(args[
i].c_str());
544 argv[
argc] =
nullptr;
551 using namespace boost::filesystem;
553 boost::system::error_code
ec;
554 auto newDir =
path(
"thread"s + std::to_string(
id));
555 create_directory(newDir, ec);
556 current_path(newDir, ec);
558 execvp(argv[0], argv);
561 while ((
write(filedes[1], &rc,
sizeof(
int)) == -1) && (errno == EINTR)) {}
566 for (
unsigned int i=0;
i<args.size()+1;
i++) {
572 throw cms::Exception(
"ForkException") <<
"Unable to fork a child (errno=" << errno <<
", " << strerror(errno) <<
")";
577 while (((rc2 = read(filedes[0], &rc,
sizeof(
int))) == -1) && (errno == EINTR)) { rc2 = 0; }
578 if ((rc2 ==
sizeof(
int)) && rc) {
579 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to execute script (errno=" << rc <<
", " << strerror(rc) <<
")";
586 if (waitpid(pid, &status, 0) < 0) {
587 if (errno == EINTR) {
590 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to read child status (errno=" << errno <<
", " << strerror(errno) <<
")";
593 if (WIFSIGNALED(status)) {
594 throw cms::Exception(
"ExternalLHEProducer") <<
"Child exited due to signal " << WTERMSIG(status) <<
".";
596 if (WIFEXITED(status)) {
597 rc = WEXITSTATUS(status);
602 throw cms::Exception(
"ExternalLHEProducer") <<
"Child failed with exit code " << rc <<
".";
613 desc.
setComment(
"Executes an external script and places its output file into an EDM collection");
618 desc.
add<std::vector<std::string> >(
"args");
619 desc.
add<uint32_t>(
"numberOfParameters");
623 ->setComment(
"If true, run the script concurrently in separate processes.");
624 desc.
addUntracked<std::vector<std::string>>(
"postGenerationCommand", std::vector<std::string>())
626 "Command to run after the generation script has completed. The first argument can be a relative path.");
629 nPartonMappingDesc.
add<
unsigned>(
"idprup");
631 nPartonMappingDesc.
add<
unsigned>(
"np");
650 newFileOpened =
false;
657 std::shared_ptr<lhef::LHERunInfo> runInfoThis =
partonLevel_->getRunInfo();
void beginRunProduce(edm::Run &run, edm::EventSetup const &es) override
void setComment(std::string const &value)
VParameterSet const & getParameterSetVector(std::string const &name) const
void endRunProduce(edm::Run &, edm::EventSetup const &) override
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
ParameterDescriptionBase * addUntracked(U const &iLabel, T const &value)
void addHeader(const Header &header)
void addComment(const std::string &line)
FunctorTask< F > * make_functor_task(ALLOC &&iAlloc, F f)
ParameterDescriptionBase * addVPSetOptional(U const &iLabel, ParameterSetDescription const &validator, std::vector< ParameterSet > const &defaults)
void produce(edm::Event &, const edm::EventSetup &) override
void executeScript(std::vector< std::string > const &args, int id, bool isPost) const
void addWeight(const WGT &wgt)
bool exists(std::string const ¶meterName) const
checks if a parameter exists
boost::ptr_deque< LHERunInfoProduct > runInfoProducts_
static void fillDescriptions(edm::ConfigurationDescriptions &descriptions)
void setComment(std::string const &value)
#define DEFINE_FWK_MODULE(type)
void addDefault(ParameterSetDescription const &psetDescription)
std::shared_ptr< lhef::LHERunInfo > runInfoLast_
bool generateConcurrently_
std::shared_ptr< lhef::LHERunInfo > runInfo_
int closeDescriptors(int preserve) const
std::unique_ptr< lhef::LHEReader > reader_
std::map< unsigned, std::pair< unsigned, unsigned > > nPartonMapping_
def pipe(cmdline, input=None)
std::vector< std::string > makeArgs(uint32_t nEvents, unsigned int nThreads, std::uint32_t seed) const
ParameterDescriptionBase * add(U const &iLabel, T const &value)
virtual std::uint32_t mySeed() const =0
const std::vector< std::string > args_
std::string outputContents_
const std::vector< std::string > postGenerationCommand_
void addComment(const std::string &line)
void preallocThreads(unsigned int) override
void put(std::unique_ptr< PROD > product)
Put a new product.
std::string fullPath() const
ExternalLHEProducer(const edm::ParameterSet &iConfig)
std::shared_ptr< lhef::LHEEvent > partonLevel_