Skip to content

Commit d170a4e

Browse files
committed
added files
0 parents  commit d170a4e

File tree

7 files changed

+526
-0
lines changed

7 files changed

+526
-0
lines changed

Pump.h

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#pragma once
2+
3+
#include <QThread>
4+
#include <QProcess>
5+
6+
class Pump : public QThread
7+
{
8+
Q_OBJECT
9+
10+
QProcess &proc;
11+
12+
public:
13+
Pump(QProcess &);
14+
void run();
15+
16+
signals:
17+
void error(QString);
18+
};

Wrapper.cpp

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
#include <QCoreApplication>
2+
3+
#include "Wrapper.h"
4+
5+
#include "print.h"
6+
#include "log.h"
7+
8+
Wrapper::Wrapper() : pump(proc)
9+
{
10+
connect(&proc, SIGNAL(error(QProcess::ProcessError)),
11+
this, SLOT(handle_error()));
12+
13+
connect(&proc, SIGNAL(readyReadStandardError()),
14+
this, SLOT(handle_stderr()));
15+
16+
connect(&proc, SIGNAL(readyReadStandardOutput()),
17+
this, SLOT(handle_stdout()));
18+
19+
connect(&proc, SIGNAL(finished(int, QProcess::ExitStatus)),
20+
this, SLOT(handle_finished(int, QProcess::ExitStatus)));
21+
22+
connect(&proc, SIGNAL(started()),
23+
this, SLOT(handle_started()));
24+
25+
connect(&timer, SIGNAL(timeout()),
26+
this, SLOT(handle_timeout()));
27+
28+
connect(&pump, SIGNAL(error(QString)),
29+
this, SLOT(handle_pump_error(QString)));
30+
31+
}
32+
33+
void
34+
Wrapper::start()
35+
{
36+
status = STARTING;
37+
38+
proc.start(command);
39+
40+
pid = proc.pid();
41+
42+
our_log( ( sprint "INFO: Starting %s[%d]\n" % name, pid ) );
43+
44+
timer.start(30*1000);
45+
46+
}
47+
48+
void
49+
Wrapper::log(const char* msg)
50+
{
51+
auto t = time(NULL);
52+
char *timestr = asctime(localtime(&t));
53+
54+
for (char *c=timestr; *c != '\0'; c++) if (*c=='\n') *c = '\0';
55+
56+
fprint (logfile) "%s %s %s[%d]: %s" % timestr, hostname, name, pid, msg;
57+
58+
if (logfile != stderr)
59+
eprint "%s[%d]: %s" % name, pid, msg;
60+
61+
fflush(logfile);
62+
}
63+
64+
void
65+
Wrapper::handle_finished(int exit_code, QProcess::ExitStatus status)
66+
{
67+
// proc.setReadChannel(QProcess::StandardError);
68+
// proc.waitForReadyRead();
69+
// proc.readLine(buf, sizeof buf);
70+
// log(buf);
71+
// printf("<<<%s>>>\n", buf);
72+
73+
handle_stdout();
74+
75+
if (status == QProcess::CrashExit)
76+
our_log( (sprint "CRITICAL: %s[%d] crashed\n" % name, pid) );
77+
else
78+
{
79+
if (exit_code == 0)
80+
our_log( (sprint "INFO: %s[%d] finished with code %d\n" % name, pid, exit_code) );
81+
else
82+
our_log( (sprint "WARN: %s[%d] finished with code %d\n" % name, pid, exit_code) );
83+
}
84+
85+
pump.terminate();
86+
pump.wait(5000);
87+
QCoreApplication::quit();
88+
}
89+
90+
void
91+
Wrapper::handle_stderr()
92+
{
93+
proc.setReadChannel(QProcess::StandardError);
94+
while (proc.canReadLine())
95+
{
96+
int count = proc.readLine(buf, sizeof buf);
97+
log(buf);
98+
}
99+
}
100+
101+
void
102+
Wrapper::handle_stdout()
103+
{
104+
proc.setReadChannel(QProcess::StandardOutput);
105+
106+
int count;
107+
108+
while ( (count = proc.read(buf, sizeof buf)) > 0 )
109+
{
110+
fwrite(buf, 1, count, stdout);
111+
}
112+
113+
fflush(stdout);
114+
115+
}
116+
117+
118+
void
119+
Wrapper::handle_error()
120+
{
121+
if (status == STARTING)
122+
our_log( (sprint "FATAL: Could not start %s[%d]: %s\n" %
123+
name, pid, proc.errorString()) );
124+
else
125+
our_log( (sprint "CRITICAL: %s[%d] encountered an error: %s\n" %
126+
name, pid, proc.errorString()) );
127+
128+
quit();
129+
}
130+
131+
void
132+
Wrapper::handle_started()
133+
{
134+
timer.stop();
135+
status = RUNNING;
136+
137+
pump.start();
138+
139+
if (timeout > 0)
140+
timer.start(timeout);
141+
}
142+
143+
void
144+
Wrapper::handle_timeout()
145+
{
146+
if (status == STARTING)
147+
our_log( ( sprint "FATAL: Could not start %s[%d]: Timed out\n" % name, pid ) );
148+
149+
else if (status == RUNNING)
150+
{
151+
status = KILLING;
152+
our_log( ( sprint "CRITICAL: %s[%d] timed out and will be killed.\n" % name, pid) );
153+
}
154+
155+
quit();
156+
}
157+
158+
void
159+
Wrapper::handle_pump_error(QString const& error)
160+
{
161+
our_log( (sprint "CRITICAL: %s[%d] encountered an error: %s\n" % name, pid, error) );
162+
163+
quit();
164+
}
165+
166+
void
167+
Wrapper::quit()
168+
{
169+
if (proc.state() != QProcess::NotRunning)
170+
proc.kill();
171+
else
172+
QCoreApplication::quit();
173+
}

Wrapper.h

+57
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
#pragma once
2+
#include <stdio.h>
3+
#include <QObject>
4+
#include <QProcess>
5+
#include <QFile>
6+
#include <QTimer>
7+
#include "Pump.h"
8+
9+
class Wrapper : public QObject
10+
{
11+
Q_OBJECT
12+
13+
enum Status {
14+
STARTING,
15+
RUNNING,
16+
KILLING
17+
};
18+
19+
public:
20+
QString command;
21+
QString name;
22+
QString hostname;
23+
int ourpid;
24+
FILE *logfile;
25+
int timeout;
26+
27+
28+
Wrapper();
29+
30+
public slots:
31+
void start();
32+
33+
34+
35+
private slots:
36+
// void handle_stdin();
37+
void handle_stderr();
38+
void handle_stdout();
39+
void handle_finished(int, QProcess::ExitStatus);
40+
void handle_error();
41+
void handle_started();
42+
void handle_timeout();
43+
void handle_pump_error(QString const&);
44+
45+
private:
46+
QProcess proc;
47+
QTimer timer;
48+
49+
char buf[1024*8];
50+
int pid;
51+
52+
void log(const char*);
53+
void quit();
54+
Status status;
55+
Pump pump;
56+
57+
};

log.h

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
#pragma once
2+
3+
#include <QString>
4+
5+
6+
7+
void our_log(QString const& str);

main.cpp

+87
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#include <stdio.h>
2+
3+
#include <QSettings>
4+
#include <QFileInfo>
5+
#include <QCoreApplication>
6+
#include <QHostInfo>
7+
#include <QTimer>
8+
9+
10+
#include "print.h"
11+
#include "Wrapper.h"
12+
13+
14+
FILE *logfile;
15+
QString hostname = QHostInfo::localHostName();
16+
int ourpid = QCoreApplication::applicationPid();
17+
18+
void our_log(QString const& str)
19+
{
20+
21+
auto t = time(NULL);
22+
char *timestr = asctime(localtime(&t));
23+
24+
for (char *c=timestr; *c != '\0'; c++) if (*c=='\n') *c = '\0';
25+
26+
if (logfile != stderr)
27+
eprint "%s" % str;
28+
29+
fprint (logfile) "%s %s wrapper[%d]: %s" % timestr, hostname, ourpid, str;
30+
31+
fflush(logfile);
32+
}
33+
34+
int main(int argc, char *argv[])
35+
{
36+
37+
if (argc != 2) {
38+
eprint "FATAL: Incorrect usage. Use: %s config.ini\n" % argv[0];
39+
return 1;
40+
}
41+
42+
QSettings settings(argv[1], QSettings::IniFormat);
43+
switch (settings.status())
44+
{
45+
case QSettings::AccessError:
46+
eprint "FATAL: Cannot access configuration file\n";
47+
return 1;
48+
49+
case QSettings::FormatError:
50+
eprint "FATAL: Format error while reading configuation file\n";
51+
return 1;
52+
53+
default:
54+
;
55+
}
56+
57+
if (! settings.contains("command") ) {
58+
eprint "FATAL: Configuration file does not contain command property";
59+
return 1;
60+
}
61+
62+
QString logfilename = settings.value("logfile", "-").toString();
63+
if (logfilename == "-")
64+
logfile = stderr;
65+
else
66+
logfile = fopen(logfilename.toLocal8Bit(), "a");
67+
68+
if (! logfile) {
69+
perror("FATAL: Could not open log file");
70+
return 1;
71+
}
72+
73+
Wrapper wrapper;
74+
wrapper.command = settings.value("command").toString();
75+
wrapper.name = settings.value("name", QFileInfo(wrapper.command).baseName()).toString();
76+
wrapper.logfile = logfile;
77+
wrapper.hostname = hostname;
78+
wrapper.ourpid = ourpid;
79+
wrapper.timeout = settings.value("timeout", -1).toInt();
80+
if (wrapper.timeout != -1)
81+
wrapper.timeout *= 1000;
82+
83+
QTimer::singleShot(0, &wrapper, SLOT(start()));
84+
85+
QCoreApplication app(argc, argv);
86+
QCoreApplication::exec();
87+
}

0 commit comments

Comments
 (0)