Skip to content

Commit 72419b0

Browse files
committed
logs
1 parent 14d973f commit 72419b0

4 files changed

Lines changed: 100 additions & 22 deletions

File tree

doc/releaseNotes.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -519,3 +519,4 @@ This file describes the main feature changes for each readout.exe released versi
519519
- First trigger received on each link should be SOC or SOT.
520520
- added equipment-cruemulator-*.PayloadSizeStdev: generate payload with random size (gaussian distribution mean=PayloadSize sigma=PayloadSizeStdev).
521521
- added equipment-cruemulator-*.linkThroughput: set incoming link data throughput (in Gbps).
522+
- Minor logging updates.

src/ReadoutEquipmentZmq.cxx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -358,7 +358,7 @@ int ReadoutEquipmentZmq::tfClientCallback(void* msg, int msgSize)
358358
tfUpdateTime = time(NULL);
359359
if (tfUpdateTimeWarning) {
360360
tfUpdateTimeWarning = 0;
361-
theLog.log(LogInfoSupport_(3236), "New TF id received from TF server");
361+
theLog.log(LogInfoDevel_(3236), "New TF id received from TF server");
362362
}
363363
if (maxTf == 0) {
364364
// that's the first TF

src/mainReadout.cxx

Lines changed: 92 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,8 @@
3232
#include <sys/wait.h>
3333
#include <string>
3434
#include <charconv>
35+
#include <atomic>
36+
#include <filesystem>
3537

3638
#include "DataBlock.h"
3739
#include "DataBlockContainer.h"
@@ -148,6 +150,50 @@ void dbLog(const std::string &msg) {
148150
theLog.log(LogInfoDevel_(3012), "%s", msg.c_str());
149151
}
150152

153+
// an object running a thread redirecting from a file descriptor to infologger
154+
// the file descriptor should be valid for the lifetime of the object
155+
class TheLogRedirection {
156+
public:
157+
TheLogRedirection(int fd, std::string name, int errcode) {
158+
this->fd = fd;
159+
this->name = name;
160+
this->errcode = errcode;
161+
shutdownRequest = 0;
162+
std::function<void(void)> f = std::bind(&TheLogRedirection::run, this);
163+
th = std::make_unique<std::thread>(f);
164+
};
165+
~TheLogRedirection() {
166+
shutdownRequest = 1;
167+
if (th != nullptr) {
168+
th->join();
169+
th = nullptr;
170+
}
171+
}
172+
private:
173+
int fd = -1; // the file descriptor to monitor
174+
std::string name; // name used as header for the output logs
175+
int errcode = 0; // an error code to be used for output messages
176+
std::unique_ptr<std::thread> th; // a thread reading from fd and injecting to theLog
177+
std::atomic<int> shutdownRequest; // flag to terminate thread
178+
void run() {
179+
setThreadName((std::string("log-") + name).c_str());
180+
if (fd>=0) {
181+
// thread loop
182+
LineBuffer b;
183+
while (!shutdownRequest) {
184+
std::string result;
185+
if (b.appendFromFileDescriptor(fd, 100)) {
186+
break;
187+
}
188+
while (!b.getNextLine(result)) {
189+
theLog.log(LogInfoDevel_(errcode), "%s: %s", name.c_str(), result.c_str());
190+
}
191+
}
192+
}
193+
theLog.log(LogInfoDevel_(errcode),"%s: logs completed", name.c_str());
194+
}
195+
};
196+
151197
class Readout
152198
{
153199

@@ -191,11 +237,13 @@ class Readout
191237
int cfgMaxMsgError; // maximum number of error messages before stopping run
192238
int cfgMaxMsgWarning; // maximum number of warning messages before stopping run
193239
int cfgCustomCommandsEnabled = 0; // when set, a sub-process bash is launched to execute custom commands
194-
std::string cfgCustomCommandsShell = "o2-readout-command-launcher"; // or leave empty for raw bash commands
240+
std::string cfgCustomCommandsShell = "/bin/sh o2-readout-command-launcher";
195241
std::map<std::string,std::string> customCommands; // map of state / command pairs to be executed
196242
pid_t customCommandsShellPid = 0; // pid of shell for custom commands
197243
int customCommandsShellFdIn = -1; // input to shell
198244
int customCommandsShellFdOut = -1; // output from shell
245+
int customCommandsShellFdErr = -1; // err from shell
246+
std::unique_ptr<TheLogRedirection> customCommandsShellLog; // thread redirecting shell stderr to infologger
199247
void executeCustomCommand(const char *stateChange); // execute a custom command for given state transition, if any
200248

201249
// runtime entities
@@ -216,8 +264,6 @@ class Readout
216264

217265
bool isError = 0; // flag set to 1 when error has been detected
218266
bool logFirstError = 0; // flag set to 1 after 1 error reported from iterateCheck/iterateRunning procedures
219-
std::vector<std::string> strErrors; // errors backlog
220-
std::mutex mutexErrors; // mutex to guard access to error variables
221267

222268
#ifdef WITH_LOGBOOK
223269
std::unique_ptr<bookkeeping::BookkeepingInterface> logbookHandle; // handle to logbook
@@ -360,9 +406,9 @@ int Readout::init(int argc, char* argv[])
360406
gReadoutStats.counters.state = stringToUint64("standby");
361407
int readoutStatsErr = gReadoutStats.startPublish(cfgStatsPublishAddress, cfgStatsPublishInterval);
362408
if (readoutStatsErr == 0) {
363-
initLogs.push_back({LogInfoSupport, "Started Stats publish @ " + cfgStatsPublishAddress});
409+
initLogs.push_back({LogInfoDevel, "Started Stats publish @ " + cfgStatsPublishAddress});
364410
} else if (readoutStatsErr > 0) {
365-
initLogs.push_back({LogWarningSupport_(3236), "Failed to start Stats publish"});
411+
initLogs.push_back({LogWarningDevel_(3236), "Failed to start Stats publish"});
366412
} //otherwise: disabled
367413

368414
// configure signal handlers for clean exit
@@ -454,38 +500,62 @@ int Readout::init(int argc, char* argv[])
454500
// init shell for custom commands
455501
if (cfgCustomCommandsEnabled) {
456502
for (;;) {
457-
int p_stdin[2], p_stdout[2];
503+
int p_stdin[2], p_stdout[2], p_stderr[2];
458504
pid_t pid;
459505

460-
if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0) break;
461-
pid = fork();
506+
if (pipe(p_stdin) != 0 || pipe(p_stdout) != 0 || pipe(p_stderr) != 0) break;
462507

508+
// create shell launching command
509+
std::vector<std::string> shellArgvStrings;
510+
getListFromString(cfgCustomCommandsShell, shellArgvStrings, ' ');
511+
if (shellArgvStrings.size()<1) {
512+
break;
513+
}
514+
theLog.log(LogInfoDevel_(3013), "Executing %s", cfgCustomCommandsShell.c_str());
515+
516+
pid = fork();
463517
if (pid < 0) {
464518
break;
465519
} else if (pid == 0) {
466520
dup2(p_stdin[0], STDIN_FILENO);
467521
dup2(p_stdout[1], STDOUT_FILENO);
522+
dup2(p_stderr[1], STDERR_FILENO);
468523
close(p_stdin[0]);
469524
close(p_stdin[1]);
470525
close(p_stdout[0]);
471526
close(p_stdout[1]);
472-
execl("/bin/sh","sh", cfgCustomCommandsShell.c_str(), NULL);
527+
close(p_stderr[0]);
528+
close(p_stderr[1]);
529+
530+
std::vector<const char*> argv;
531+
std::string filename = std::filesystem::path(shellArgvStrings[0]).filename();
532+
argv.push_back(filename.c_str());
533+
for(unsigned int i = 1; i< shellArgvStrings.size(); i++) {
534+
argv.push_back(shellArgvStrings[i].c_str());
535+
}
536+
argv.push_back(NULL);
537+
fprintf(stderr, "%s\n", shellArgvStrings[0].c_str());
538+
execv(shellArgvStrings[0].c_str(), (char* const*)&argv[0]);
539+
fprintf(stderr, "Failed to start shell for custom commands: %s\n", strerror(errno));
473540
exit(1);
474541
}
475542
close(p_stdin[0]);
476543
close(p_stdout[1]);
544+
close(p_stderr[1]);
477545
customCommandsShellFdIn = p_stdin[1];
478546
customCommandsShellFdOut = p_stdout[0];
547+
customCommandsShellFdErr = p_stderr[0];
479548
customCommandsShellPid = pid;
480549
break;
481550
}
482551
if (customCommandsShellPid) {
483-
theLog.log(LogInfoDevel_(3013), "Shell started for custom commands - pid %d", (int)customCommandsShellPid);
552+
// create a thread to redirect stderr shell output
553+
customCommandsShellLog = std::make_unique<TheLogRedirection>(customCommandsShellFdErr, "shell", 3013);
554+
theLog.log(LogInfoDevel_(3013), "Process started for custom commands - pid %d", (int)customCommandsShellPid);
484555
} else {
485556
cfgCustomCommandsEnabled = 0;
486557
}
487558
}
488-
489559
// print some built-in constants
490560
if (cfgVerbose) {
491561
// theLog.log(LogInfoDevel, "DataBlockHeader size = %d", (int)sizeof(DataBlockHeader));
@@ -529,7 +599,7 @@ int Readout::configure(const boost::property_tree::ptree& properties)
529599
#endif
530600
}
531601
} catch (std::string err) {
532-
theLog.log(LogErrorSupport_(3100), "%s", err.c_str());
602+
theLog.log(LogErrorSupport_(3100), "Failed to read config: %s", err.c_str());
533603
return -1;
534604
}
535605

@@ -600,7 +670,9 @@ int Readout::configure(const boost::property_tree::ptree& properties)
600670
theLog.log(LogWarningDevel_(3102), "Failed to parse custom commands");
601671
customCommands.clear();
602672
} else {
603-
theLog.log(LogInfoDevel_(3013), "Registered custom commands:");
673+
if (customCommands.size()) {
674+
theLog.log(LogInfoDevel_(3013), "Registered custom commands:");
675+
}
604676
for (const auto &kv : customCommands) {
605677
theLog.log(LogInfoDevel_(3013), "%s : %s", kv.first.c_str(), kv.second.c_str());
606678
}
@@ -1597,6 +1669,10 @@ Readout::~Readout() {
15971669
theLog.log(LogInfoDevel_(3013), "Killing %d", (int)customCommandsShellPid);
15981670
kill(customCommandsShellPid, SIGKILL);
15991671
}
1672+
if (customCommandsShellFdErr >= 0) {
1673+
customCommandsShellLog = nullptr;
1674+
close(customCommandsShellFdErr);
1675+
}
16001676
}
16011677

16021678
#ifdef WITH_DB
@@ -1615,7 +1691,9 @@ void Readout::executeCustomCommand(const char *stateChange) {
16151691
fsync(customCommandsShellFdIn);
16161692
LineBuffer b;
16171693
const int cmdTimeout = 10000; // 10s timeout
1618-
b.appendFromFileDescriptor(customCommandsShellFdOut, cmdTimeout);
1694+
if (b.appendFromFileDescriptor(customCommandsShellFdOut, cmdTimeout)) {
1695+
theLog.log(LogInfoDevel_(3013), "Command launcher unavailable"); // EOF
1696+
}
16191697
std::string result;
16201698
if (b.getNextLine(result) == 0) {
16211699
theLog.log(LogInfoDevel_(3013), "Command executed: %s", result.c_str());

src/readoutCommandLauncher.sh

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,9 @@
33
# invoked by o2-readout-exe
44
# if launched without argument, read commands from stdin line by line
55

6-
# ensure log output not going to stdout
7-
unset O2_INFOLOGGER_MODE
6+
# ensure log output not going to stdout, all goes to stderr
87

9-
LOG="/opt/o2-InfoLogger/bin/o2-infologger-log -oFacility=readout -oLevel=11 -oErrorCode=3013"
8+
LOG="eval >&2 echo"
109
CMD="'$*'"
1110

1211
if [ "$1" == "" ]; then
@@ -15,14 +14,14 @@ if [ "$1" == "" ]; then
1514
while read line
1615
do
1716
$LOG "Executing command $line"
18-
eval $line 2>&1 | $LOG -x -oSeverity=Debug
17+
>&2 eval $line
1918

2019
if [ 0 -eq ${PIPESTATUS[0]} ]; then
2120
echo "ok"
2221
$LOG "Command ok"
2322
else
2423
echo "error"
25-
$LOG -oSeverity=Error "Command error"
24+
$LOG "Command error"
2625
fi
2726
done
2827
$LOG "Exiting command launcher"
@@ -31,15 +30,15 @@ if [ "$1" == "" ]; then
3130
else
3231

3332
$LOG "Executing command $CMD"
34-
$@ 2>&1 | $LOG -x -oSeverity=Debug
33+
>&2 $@
3534

3635
if [ 0 -eq ${PIPESTATUS[0]} ]; then
3736
echo "ok"
3837
$LOG "Command ok"
3938
exit 0
4039
else
4140
echo "error"
42-
$LOG -oSeverity=Error "Command error"
41+
$LOG "Command error"
4342
exit 1
4443
fi
4544

0 commit comments

Comments
 (0)