26 #include "boost/filesystem.hpp" 32 #include <sys/resource.h> 33 #include "tbb/task_arena.h" 36 #include "boost/bind.hpp" 37 #include "boost/shared_ptr.hpp" 38 #include "boost/ptr_container/ptr_deque.hpp" 73 edm::EndRunProducer> {
95 const std::vector<std::string>
args_;
130 scriptName_((iConfig.getParameter<
edm::FileInPath>(
"scriptName")).fullPath()),
133 npars_(iConfig.getParameter<uint32_t>(
"numberOfParameters")),
134 nEvents_(iConfig.getUntrackedParameter<uint32_t>(
"nEvents")),
139 throw cms::Exception(
"ExternalLHEProducer") <<
"Problem with configuration: " <<
args_.size() <<
" script arguments given, expected " <<
npars_;
141 if (iConfig.
exists(
"nPartonMapping")) {
143 for (
auto&
cfg : processMap) {
144 unsigned processId(
cfg.getParameter<
unsigned>(
"idprup"));
148 if (orderStr ==
"LO")
150 else if (orderStr ==
"NLO")
153 throw cms::Exception(
"ExternalLHEProducer") <<
"Invalid order specification for process " << processId <<
": " << orderStr;
155 unsigned np(
cfg.getParameter<
unsigned>(
"np"));
161 produces<LHEXMLStringProduct, edm::Transition::BeginRun>(
"LHEScriptOutput");
163 produces<LHEEventProduct>();
164 produces<LHERunInfoProduct, edm::Transition::BeginRun>();
165 produces<LHERunInfoProduct, edm::Transition::EndRun>();
187 <<
"The likely cause is that the lhe file contains fewer events than were requested, which is possible " 188 <<
"in case of phase space integration or uneweighting efficiency problems.";
191 std::unique_ptr<LHEEventProduct> product(
214 order = procDef.first;
217 catch (std::out_of_range&) {
223 product->setNpLO(np);
224 product->setNpNLO(-1);
227 product->setNpLO(-1);
228 product->setNpNLO(np);
244 std::for_each(
runInfo_->getHeaders().begin(),
248 std::for_each(
runInfo_->getComments().begin(),
282 <<
"The ExternalLHEProducer module requires the RandomNumberGeneratorService\n" 283 "which is not present in the configuration file. You must add the service\n" 284 "in the configuration file if you want to run ExternalLHEProducer";
287 std::vector<std::string> infiles;
293 std::exception_ptr except;
294 std::atomic<char> exceptSet{0};
296 tbb::this_task_arena::isolate([
this, &except, &infiles, &exceptSet, nEventsAve, overflow,
seed]() {
297 tbb::empty_task* waitTask =
new (tbb::task::allocate_root()) tbb::empty_task;
302 if (
nEvents_ % nThreads_ != 0 and
t >= overflow) {
306 [
t,
this, &infiles,
seed, nEvents, &except, &exceptSet, waitTask]() {
308 using namespace boost::filesystem;
311 infiles[
t] =
out.native();
315 if (exceptSet.compare_exchange_strong(expected, 1)) {
316 except = std::current_exception();
320 waitTask->decrement_ref_count();
322 tbb::task::spawn(*
task);
324 waitTask->wait_for_all();
327 if (exceptSet != 0) {
328 std::rethrow_exception(except);
331 infiles = std::vector<std::string>(1,
outputFile_);
342 using namespace boost::filesystem;
347 std::ifstream instream(file);
351 instream.seekg (0, instream.end);
352 int insize = instream.tellg();
353 instream.seekg (0, instream.beg);
354 p->fillCompressedContent(instream, 0.25*insize);
362 unsigned int skip = 0;
363 reader_ = std::make_unique<lhef::LHEReader>(infiles,
skip);
370 std::for_each(
runInfo_->getHeaders().begin(),
374 std::for_each(
runInfo_->getComments().begin(),
396 std::unique_ptr<LHERunInfoProduct> product(
runInfoProducts_.pop_front().release());
403 <<
"Event loop is over, but there are still lhe events to process." 404 <<
"This could happen if lhe file contains more events than requested. This is never expected to happen.";
410 using namespace boost::filesystem;
413 if (unlink(
out.c_str())) {
414 throw cms::Exception(
"OutputDeleteError") <<
"Unable to delete original script output file " <<
out 415 <<
" (errno=" << errno <<
", " << strerror(errno) <<
").";
421 <<
" (errno=" << errno <<
", " << strerror(errno) <<
").";
428 std::uint32_t
seed)
const {
429 std::vector<std::string>
args;
430 args.reserve(3 +
args_.size());
432 args.push_back(
args_.front());
433 args.push_back(std::to_string(nEvents));
435 args.push_back(std::to_string(seed));
437 args.push_back(std::to_string(nThreads));
440 for (
unsigned int iArg = 0; iArg < args.size(); iArg++) {
441 LogDebug(
"LHEInputArgs") <<
"arg [" << iArg <<
"] = " << args[iArg];
457 if ((dir = opendir(
"/proc/self/fd"))) {
459 while ((dp = readdir (dir)) !=
nullptr) {
460 if ((strcmp(dp->d_name,
".") == 0) || (strcmp(dp->d_name,
"..") == 0)) {
463 if (sscanf(dp->d_name,
"%d", &fd) != 1) {
479 for (fd=3; fd<maxfd+1; fd++) {
494 int filedes[2], fd_flags;
501 if ((fd_flags = fcntl(filedes[1], F_GETFD,
NULL)) == -1) {
502 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to get pipe file descriptor flags (errno=" << rc <<
", " << strerror(rc) <<
")";
504 if (fcntl(filedes[1], F_SETFD, fd_flags | FD_CLOEXEC) == -1) {
505 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to set pipe file descriptor flags (errno=" << rc <<
", " << strerror(rc) <<
")";
508 unsigned int argc = 1 + args.size();
510 char **
argv =
new char *[argc+1];
512 for (
unsigned int i=1;
i<
argc;
i++) {
513 argv[
i] = strdup(args[
i-1].c_str());
515 argv[
argc] =
nullptr;
522 using namespace boost::filesystem;
524 boost::system::error_code
ec;
525 auto newDir =
path(
"thread"s + std::to_string(
id));
526 create_directory(newDir, ec);
527 current_path(newDir, ec);
529 execvp(argv[0], argv);
532 while ((
write(filedes[1], &rc,
sizeof(
int)) == -1) && (errno == EINTR)) {}
537 for (
unsigned int i=0;
i<args.size()+1;
i++) {
543 throw cms::Exception(
"ForkException") <<
"Unable to fork a child (errno=" << errno <<
", " << strerror(errno) <<
")";
548 while (((rc2 = read(filedes[0], &rc,
sizeof(
int))) == -1) && (errno == EINTR)) { rc2 = 0; }
549 if ((rc2 ==
sizeof(
int)) && rc) {
550 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to execute script (errno=" << rc <<
", " << strerror(rc) <<
")";
557 if (waitpid(pid, &status, 0) < 0) {
558 if (errno == EINTR) {
561 throw cms::Exception(
"ExternalLHEProducer") <<
"Failed to read child status (errno=" << errno <<
", " << strerror(errno) <<
")";
564 if (WIFSIGNALED(status)) {
565 throw cms::Exception(
"ExternalLHEProducer") <<
"Child exited due to signal " << WTERMSIG(status) <<
".";
567 if (WIFEXITED(status)) {
568 rc = WEXITSTATUS(status);
573 throw cms::Exception(
"ExternalLHEProducer") <<
"Child failed with exit code " << rc <<
".";
584 desc.
setComment(
"Executes an external script and places its output file into an EDM collection");
589 desc.
add<std::vector<std::string> >(
"args");
590 desc.
add<uint32_t>(
"numberOfParameters");
594 ->setComment(
"If true, run the script concurrently in separate processes.");
597 nPartonMappingDesc.
add<
unsigned>(
"idprup");
599 nPartonMappingDesc.
add<
unsigned>(
"np");
618 newFileOpened =
false;
625 std::shared_ptr<lhef::LHERunInfo> runInfoThis =
partonLevel_->getRunInfo();
void beginRunProduce(edm::Run &run, edm::EventSetup const &es) override
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 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_
void addComment(const std::string &line)
void executeScript(std::vector< std::string > const &args, int id) const
void preallocThreads(unsigned int) override
void put(std::unique_ptr< PROD > product)
Put a new product.
ExternalLHEProducer(const edm::ParameterSet &iConfig)
std::shared_ptr< lhef::LHEEvent > partonLevel_