27 #include <system_error>
32 #include <sys/resource.h>
33 #include "tbb/task_arena.h"
35 #include "boost/ptr_container/ptr_deque.hpp"
90 const std::vector<std::string>
args_;
127 : scriptName_((iConfig.getParameter<
edm::FileInPath>(
"scriptName")).
fullPath()),
128 outputFile_(iConfig.getParameter<
std::
string>(
"outputFile")),
130 npars_(iConfig.getParameter<uint32_t>(
"numberOfParameters")),
131 nEvents_(iConfig.getUntrackedParameter<uint32_t>(
"nEvents")),
132 storeXML_(iConfig.getUntrackedParameter<
bool>(
"storeXML")),
133 generateConcurrently_(iConfig.getUntrackedParameter<
bool>(
"generateConcurrently")) {
136 <<
"Problem with configuration: " <<
args_.size() <<
" script arguments given, expected " <<
npars_;
138 if (iConfig.
exists(
"nPartonMapping")) {
140 for (
auto&
cfg : processMap) {
141 unsigned processId(
cfg.getParameter<
unsigned>(
"idprup"));
145 if (orderStr ==
"LO")
147 else if (orderStr ==
"NLO")
151 <<
"Invalid order specification for process " << processId <<
": " << orderStr;
153 unsigned np(
cfg.getParameter<
unsigned>(
"np"));
159 produces<LHEXMLStringProduct, edm::Transition::BeginRun>(
"LHEScriptOutput");
161 produces<LHEEventProduct>();
162 produces<LHERunInfoProduct, edm::Transition::BeginRun>();
163 produces<LHERunInfoProduct, edm::Transition::EndRun>();
178 <<
"No lhe event found in ExternalLHEProducer::produce(). "
179 <<
"The likely cause is that the lhe file contains fewer events than were requested, which is possible "
180 <<
"in case of phase space integration or uneweighting efficiency problems.";
183 std::unique_ptr<LHEEventProduct> product(
202 order = procDef.first;
204 }
catch (std::out_of_range&) {
206 <<
"Unexpected IDPRUP encountered: " <<
partonLevel_->getHEPEUP()->IDPRUP;
211 product->setNpLO(
np);
212 product->setNpNLO(-1);
215 product->setNpLO(-1);
216 product->setNpNLO(
np);
231 std::for_each(
runInfo_->getHeaders().begin(),
234 std::for_each(
runInfo_->getComments().begin(),
264 <<
"The ExternalLHEProducer module requires the RandomNumberGeneratorService\n"
265 "which is not present in the configuration file. You must add the service\n"
266 "in the configuration file if you want to run ExternalLHEProducer";
269 std::vector<std::string> infiles;
275 std::exception_ptr except;
276 std::atomic<char> exceptSet{0};
278 tbb::this_task_arena::isolate([
this, &except, &infiles, &exceptSet, nEventsAve, overflow,
seed]() {
279 tbb::empty_task* waitTask =
new (tbb::task::allocate_root()) tbb::empty_task;
288 [
t,
this, &infiles,
seed,
nEvents, &except, &exceptSet, waitTask]() {
290 using namespace std::filesystem;
291 using namespace std::string_literals;
293 infiles[
t] =
out.native();
297 if (exceptSet.compare_exchange_strong(expected, 1)) {
298 except = std::current_exception();
302 waitTask->decrement_ref_count();
304 tbb::task::spawn(*
task);
306 waitTask->wait_for_all();
307 tbb::task::destroy(*waitTask);
309 if (exceptSet != 0) {
310 std::rethrow_exception(except);
313 infiles = std::vector<std::string>(1,
outputFile_);
324 using namespace std::filesystem;
329 std::ifstream instream(
file);
333 instream.seekg(0, instream.end);
334 int insize = instream.tellg();
335 instream.seekg(0, instream.beg);
336 p->fillCompressedContent(instream, 0.25 * insize);
344 unsigned int skip = 0;
345 reader_ = std::make_unique<lhef::LHEReader>(infiles,
skip);
352 std::for_each(
runInfo_->getHeaders().begin(),
355 std::for_each(
runInfo_->getComments().begin(),
372 std::unique_ptr<LHERunInfoProduct> product(
runInfoProducts_.front().release());
380 <<
"Error in ExternalLHEProducer::endRunProduce(). "
381 <<
"Event loop is over, but there are still lhe events to process."
382 <<
"This could happen if lhe file contains more events than requested. This is never expected to happen.";
388 using namespace std::filesystem;
389 using namespace std::string_literals;
391 if (unlink(
out.c_str())) {
392 throw cms::Exception(
"OutputDeleteError") <<
"Unable to delete original script output file " <<
out
393 <<
" (errno=" << errno <<
", " << strerror(errno) <<
").";
399 <<
" (errno=" << errno <<
", " << strerror(errno) <<
").";
406 std::uint32_t
seed)
const {
407 std::vector<std::string>
args;
413 args.push_back(std::to_string(
seed));
418 for (
unsigned int iArg = 0; iArg <
args.size(); iArg++) {
419 LogDebug(
"LHEInputArgs") <<
"arg [" << iArg <<
"] = " <<
args[iArg];
433 if ((
dir = opendir(
"/proc/self/fd"))) {
435 while ((
dp = readdir(
dir)) !=
nullptr) {
436 if ((strcmp(
dp->d_name,
".") == 0) || (strcmp(
dp->d_name,
"..") == 0)) {
439 if (sscanf(
dp->d_name,
"%d", &
fd) != 1) {
455 for (
fd = 3;
fd < maxfd + 1;
fd++) {
467 int filedes[2], fd_flags;
474 if ((fd_flags = fcntl(filedes[1], F_GETFD,
NULL)) == -1) {
476 <<
"Failed to get pipe file descriptor flags (errno=" << rc <<
", " << strerror(rc) <<
")";
478 if (fcntl(filedes[1], F_SETFD, fd_flags | FD_CLOEXEC) == -1) {
480 <<
"Failed to set pipe file descriptor flags (errno=" << rc <<
", " << strerror(rc) <<
")";
483 unsigned int argc = 1 +
args.size();
487 for (
unsigned int i = 1;
i <
argc;
i++) {
497 using namespace std::filesystem;
498 using namespace std::string_literals;
500 auto newDir =
path(
"thread"s + std::to_string(
id));
501 create_directory(newDir, ec);
502 current_path(newDir, ec);
507 while ((
write(filedes[1], &rc,
sizeof(
int)) == -1) && (errno == EINTR)) {
513 for (
unsigned int i = 0;
i <
args.size() + 1;
i++) {
520 <<
"Unable to fork a child (errno=" << errno <<
", " << strerror(errno) <<
")";
525 while (((rc2 =
read(filedes[0], &rc,
sizeof(
int))) == -1) && (errno == EINTR)) {
528 if ((rc2 ==
sizeof(
int)) && rc) {
530 <<
"Failed to execute script (errno=" << rc <<
", " << strerror(rc) <<
")";
537 if (waitpid(pid, &
status, 0) < 0) {
538 if (errno == EINTR) {
542 <<
"Failed to read child status (errno=" << errno <<
", " << strerror(errno) <<
")";
545 if (WIFSIGNALED(
status)) {
546 throw cms::Exception(
"ExternalLHEProducer") <<
"Child exited due to signal " << WTERMSIG(
status) <<
".";
554 throw cms::Exception(
"ExternalLHEProducer") <<
"Child failed with exit code " << rc <<
".";
563 desc.setComment(
"Executes an external script and places its output file into an EDM collection");
568 desc.add<std::vector<std::string>>(
"args");
569 desc.add<uint32_t>(
"numberOfParameters");
570 desc.addUntracked<uint32_t>(
"nEvents");
571 desc.addUntracked<
bool>(
"storeXML",
false);
572 desc.addUntracked<
bool>(
"generateConcurrently",
false)
573 ->setComment(
"If true, run the script concurrently in separate processes.");
576 nPartonMappingDesc.
add<
unsigned>(
"idprup");
578 nPartonMappingDesc.
add<
unsigned>(
"np");
579 desc.addVPSetOptional(
"nPartonMapping", nPartonMappingDesc);
597 newFileOpened =
false;
604 std::shared_ptr<lhef::LHERunInfo> runInfoThis =
partonLevel_->getRunInfo();