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 uneweighting efficiency problems.";
194 std::unique_ptr<LHEEventProduct> product(
217 order = procDef.first;
220 catch (std::out_of_range&) {
226 product->setNpLO(np);
227 product->setNpNLO(-1);
230 product->setNpLO(-1);
231 product->setNpNLO(np);
247 std::for_each(
runInfo_->getHeaders().begin(),
251 std::for_each(
runInfo_->getComments().begin(),
285 <<
"The ExternalLHEProducer module requires the RandomNumberGeneratorService\n" 286 "which is not present in the configuration file. You must add the service\n" 287 "in the configuration file if you want to run ExternalLHEProducer";
290 std::vector<std::string> infiles;
296 std::exception_ptr except;
297 std::atomic<char> exceptSet{0};
299 tbb::this_task_arena::isolate([
this, &except, &infiles, &exceptSet, nEventsAve, overflow,
seed]() {
300 tbb::empty_task* waitTask =
new (tbb::task::allocate_root()) tbb::empty_task;
305 if (
nEvents_ % nThreads_ != 0 and
t >= overflow) {
309 [
t,
this, &infiles,
seed, nEvents, &except, &exceptSet, waitTask]() {
311 using namespace boost::filesystem;
314 infiles[
t] =
out.native();
318 if (exceptSet.compare_exchange_strong(expected, 1)) {
319 except = std::current_exception();
323 waitTask->decrement_ref_count();
325 tbb::task::spawn(*
task);
327 waitTask->wait_for_all();
330 if (exceptSet != 0) {
331 std::rethrow_exception(except);
334 infiles = std::vector<std::string>(1,
outputFile_);
344 edm::LogWarning(
"ExternalLHEProducer") << postcmd[0] <<
" is not a relative path. Run it as a shell command.";
356 using namespace boost::filesystem;
361 std::ifstream instream(file);
365 instream.seekg (0, instream.end);
366 int insize = instream.tellg();
367 instream.seekg (0, instream.beg);
368 p->fillCompressedContent(instream, 0.25*insize);
376 unsigned int skip = 0;
377 reader_ = std::make_unique<lhef::LHEReader>(infiles,
skip);
384 std::for_each(
runInfo_->getHeaders().begin(),
388 std::for_each(
runInfo_->getComments().begin(),
410 std::unique_ptr<LHERunInfoProduct> product(
runInfoProducts_.pop_front().release());
417 if (std::getenv(
"VALIDATION_RUN") !=
nullptr) {
419 <<
"Event loop is over, but there are still lhe events to process, ignoring...";
422 <<
"Error in ExternalLHEProducer::endRunProduce(). " 423 <<
"Event loop is over, but there are still lhe events to process." 424 <<
"This could happen if lhe file contains more events than requested. This is never expected to happen.";
431 using namespace boost::filesystem;
434 if (unlink(
out.c_str())) {
435 throw cms::Exception(
"OutputDeleteError") <<
"Unable to delete original script output file " <<
out 436 <<
" (errno=" << errno <<
", " << strerror(errno) <<
").";
442 <<
" (errno=" << errno <<
", " << strerror(errno) <<
").";
449 std::uint32_t
seed)
const {
450 std::vector<std::string>
args;
451 args.reserve(3 +
args_.size());
453 args.push_back(
args_.front());
454 args.push_back(std::to_string(nEvents));
456 args.push_back(std::to_string(seed));
458 args.push_back(std::to_string(nThreads));
461 for (
unsigned int iArg = 0; iArg < args.size(); iArg++) {
462 LogDebug(
"LHEInputArgs") <<
"arg [" << iArg <<
"] = " << args[iArg];
478 if ((dir = opendir(
"/proc/self/fd"))) {
480 while ((dp = readdir (dir)) !=
nullptr) {
481 if ((strcmp(dp->d_name,
".") == 0) || (strcmp(dp->d_name,
"..") == 0)) {
484 if (sscanf(dp->d_name,
"%d", &fd) != 1) {
500 for (fd=3; fd<maxfd+1; fd++) {
515 int filedes[2], fd_flags;
522 if ((fd_flags = fcntl(filedes[1], F_GETFD,
NULL)) == -1) {
523 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to get pipe file descriptor flags (errno=" << rc <<
", " << strerror(rc) <<
")";
525 if (fcntl(filedes[1], F_SETFD, fd_flags | FD_CLOEXEC) == -1) {
526 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to set pipe file descriptor flags (errno=" << rc <<
", " << strerror(rc) <<
")";
529 unsigned int argc_pre = 0;
534 unsigned int argc = argc_pre + args.size();
536 char **
argv =
new char *[argc+1];
540 for (
unsigned int i = 0;
i < args.size();
i++) {
541 argv[argc_pre +
i] = strdup(args[
i].c_str());
543 argv[
argc] =
nullptr;
550 using namespace boost::filesystem;
552 boost::system::error_code
ec;
553 auto newDir =
path(
"thread"s + std::to_string(
id));
554 create_directory(newDir, ec);
555 current_path(newDir, ec);
557 execvp(argv[0], argv);
560 while ((
write(filedes[1], &rc,
sizeof(
int)) == -1) && (errno == EINTR)) {}
565 for (
unsigned int i=0;
i<args.size()+1;
i++) {
571 throw cms::Exception(
"ForkException") <<
"Unable to fork a child (errno=" << errno <<
", " << strerror(errno) <<
")";
576 while (((rc2 = read(filedes[0], &rc,
sizeof(
int))) == -1) && (errno == EINTR)) { rc2 = 0; }
577 if ((rc2 ==
sizeof(
int)) && rc) {
578 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to execute script (errno=" << rc <<
", " << strerror(rc) <<
")";
585 if (waitpid(pid, &status, 0) < 0) {
586 if (errno == EINTR) {
589 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to read child status (errno=" << errno <<
", " << strerror(errno) <<
")";
592 if (WIFSIGNALED(status)) {
593 throw cms::Exception(
"ExternalLHEProducer") <<
"Child exited due to signal " << WTERMSIG(status) <<
".";
595 if (WIFEXITED(status)) {
596 rc = WEXITSTATUS(status);
601 throw cms::Exception(
"ExternalLHEProducer") <<
"Child failed with exit code " << rc <<
".";
612 desc.
setComment(
"Executes an external script and places its output file into an EDM collection");
617 desc.
add<std::vector<std::string> >(
"args");
618 desc.
add<uint32_t>(
"numberOfParameters");
622 ->setComment(
"If true, run the script concurrently in separate processes.");
623 desc.
addUntracked<std::vector<std::string>>(
"postGenerationCommand", std::vector<std::string>())
625 "Command to run after the generation script has completed. The first argument can be a relative path.");
628 nPartonMappingDesc.
add<
unsigned>(
"idprup");
630 nPartonMappingDesc.
add<
unsigned>(
"np");
649 newFileOpened =
false;
656 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_