Skip to content

Commit e2a9c02

Browse files
committed
Added process manager
Added a process manager to more gracefully handle launching and stopping each individual process. It's still a little rough around the edges, but it works well enough for now... I hope :S More testing is needed, and will be done.
1 parent 2af0c42 commit e2a9c02

12 files changed

+205
-49
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ install-sh
1818
minimalraw.log
1919
missing
2020
src/librenzoku.a
21+
*/tags
2122
test-driver
2223
tests/test-suite.log
2324
tests/test_runner*

src/Makefile.am

+3-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
#CFLAGS = --pedantic -Wall -std=c99 -O2
22
#CXXFLAGS = -Wall -g -Isrc/ -static -lyaml-cpp -std=c++11
3-
AM_CXXFLAGS = --pedantic -Wall -O2 -std=c++11
3+
AM_CXXFLAGS = --pedantic -Wall -O2 -g -std=c++11
44
AM_LDFLAGS = -Bstatic -lyaml-cpp -Bdynamic
55

66
# this lists the binaries to produce, the (non-PHONY, binary) targets in
@@ -25,6 +25,8 @@ librenzoku_a_SOURCES = \
2525
log.hpp \
2626
process.cpp \
2727
process.hpp \
28+
procman.cpp \
29+
procman.hpp \
2830
signals.cpp \
2931
signals.hpp \
3032
util.cpp \

src/config.cpp

+14-31
Original file line numberDiff line numberDiff line change
@@ -43,23 +43,25 @@
4343
#include "util.hpp"
4444
#include "log.hpp"
4545

46-
Config::Config(iLogger *logger) :
46+
Config::Config(iLogger *logger, ProcessManager* pm) :
4747
mWatch(),
4848
mCompile(),
4949
mTest(),
5050
mProgram(),
51+
procman(pm),
5152
logger(logger)
5253
{
5354
std::ifstream file;
5455
this->findConfig(file);
5556
this->parseConfig(file);
5657
}
5758

58-
Config::Config(iLogger *logger, std::istream& file) :
59+
Config::Config(iLogger *logger, ProcessManager* pm, std::istream& file) :
5960
mWatch(),
6061
mCompile(),
6162
mTest(),
6263
mProgram(),
64+
procman(pm),
6365
logger(logger)
6466
{
6567
this->parseConfig(file);
@@ -83,11 +85,6 @@ Config::~Config()
8385
delete [] mProgram.command[i];
8486
delete [] mProgram.command;
8587
}
86-
for(Process* proc : processes)
87-
{
88-
if(proc)
89-
delete proc;
90-
}
9188
}
9289

9390
void Config::findConfig(std::ifstream& is)
@@ -120,20 +117,26 @@ void Config::parseConfig(std::istream& file)
120117
else if(key == "program")
121118
{
122119
this->parseCommand(it->second, mProgram);
120+
if(procman->getProgram()) {
121+
throw std::runtime_error("Program already set!");
122+
}
123123
if(mProgram.command && mProgram.enabled)
124-
processes.push_back(new Process(logger, mProgram.command, true));
124+
procman->setProgram(new Process(logger, mProgram.command, true));
125125
}
126126
else if(key == "test")
127127
{
128128
this->parseCommand(it->second, mTest);
129129
if(mTest.command && mTest.enabled)
130-
processes.push_back(new Process(logger, mTest.command, true));
130+
procman->addProcess(new Process(logger, mTest.command, true));
131131
}
132132
else if(key == "compile")
133133
{
134134
this->parseCommand(it->second, mCompile);
135+
if(procman->getBuildStep()) {
136+
throw std::runtime_error("BuildStage already set!");
137+
}
135138
if(mCompile.command && mCompile.enabled)
136-
processes.push_back(new Process(logger, mCompile.command, true));
139+
procman->setBuilder(new Process(logger, mCompile.command, true));
137140
}
138141
else
139142
{
@@ -200,27 +203,7 @@ void Config::parseCommand(const YAML::Node& node, iCommandConfig& config)
200203

201204
void Config::restartProcesses()
202205
{
203-
for(Process* proc : processes)
204-
{
205-
if(proc->kill())
206-
{
207-
if(proc != processes.back())
208-
{
209-
if(proc->runAndWait())
210-
{
211-
LOG(logger, SUCCESS, "Successfully ran command");
212-
}
213-
else
214-
{
215-
LOG(logger, ERROR, "A command failed to run :(");
216-
}
217-
}
218-
else
219-
{
220-
proc->run();
221-
}
222-
}
223-
}
206+
procman->restartAll();
224207
}
225208

226209
void Config::parseWatcher(const YAML::Node& node)

src/config.hpp

+4-4
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include <yaml-cpp/yaml.h>
4141
#include "process.hpp"
4242
#include "log.hpp"
43+
#include "procman.hpp"
4344

4445
#define CONFIG_NAME "renzoku.conf"
4546

@@ -77,7 +78,7 @@ class Config {
7778
#define CONFIG_SECTION(X) X##Config m##X;
7879
#include "config_sections.hpp"
7980
#undef CONFIG_SECTION
80-
std::vector<Process*> processes;
81+
ProcessManager* procman;
8182
iLogger* logger;
8283
void parseWatcher(const YAML::Node&);
8384
void parseCommand(const YAML::Node&, iCommandConfig&);
@@ -89,13 +90,12 @@ class Config {
8990
#include "config_sections.hpp"
9091
#undef CONFIG_SECTION
9192
};
92-
Config(iLogger*);
93-
Config(iLogger*, std::istream&);
93+
Config(iLogger*, ProcessManager*);
94+
Config(iLogger*, ProcessManager*, std::istream&);
9495
~Config();
9596
inline WatchConfig getWatchConfig() { return mWatch; };
9697
inline CompileConfig getCompileConfig() { return mCompile; };
9798
inline TestConfig getTestConfig() { return mTest; };
9899
inline ProgramConfig getProgramConfig() { return mProgram; };
99-
inline std::vector<Process*> getProcesses() const { return processes; };
100100
void restartProcesses();
101101
};

src/log.cpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ std::string iLogger::createMessage(LogLevel level, const char* format, va_list
134134
var_copy) + 1;
135135
char* buffer = new char[ string_size + 10 ];
136136
buffer[0] = 0;
137-
char* f = new char[final_format.str().length()+1];
138-
strcpy(f, final_format.str().c_str());
139-
vsprintf( buffer, f, arguments );
137+
//char* f = new char[final_format.str().length()+1];
138+
//strcpy(f, final_format.str().c_str());
139+
vsprintf( buffer, final_format.str().c_str(), arguments );
140140
//#pragma GCC diagnostic pop
141141
std::string ret = std::string( buffer, string_size - 1 );
142142
delete [] buffer;

src/main.cpp

+4-2
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
#include "config.hpp"
4141
#include "log.hpp"
4242
#include "watcher.hpp"
43+
#include "procman.hpp"
4344

4445
volatile sig_atomic_t gRunning = 1;
4546

@@ -50,8 +51,9 @@ int main(int argc, char** argv) {
5051
sigaction(SIGINT,&int_catcher,0);
5152
//watcher();
5253
StdoutLogger logger;
53-
Config config(&logger);
54-
Watcher w(&logger, "./", config, true);
54+
ProcessManager procman(&logger);
55+
Config config(&logger, &procman);
56+
Watcher w(&logger, "./", config, &procman, true);
5557

5658
while(gRunning)
5759
w.listen();

src/process.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ bool Process::run()
9393
size += strlen(mCommand[i]) + 1;
9494
i++;
9595
}
96-
char* args_string = new char[size];
96+
char* args_string = new char[size + 1];
9797
//strcpy(args_string, mCommand[0]);
9898
args_string[0] = '\0';
9999
for(size_t i2 = 1; mCommand[i2] != NULL; i2++) {

src/procman.cpp

+119
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
/*
2+
* Renzoku - Re-build, re-test, and re-run a program whenever the code changes
3+
* Copyright (C) 2015 Colton Wolkins
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2.1 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*
19+
*/
20+
#include <stdexcept>
21+
#include "procman.hpp"
22+
23+
ProcessManager::ProcessManager(iLogger *logger) :
24+
mBuildStep(NULL),
25+
mProgram(NULL),
26+
logger(logger)
27+
{
28+
}
29+
30+
ProcessManager::~ProcessManager() {
31+
for(Process* proc : mProcesses)
32+
delete proc;
33+
delete mBuildStep;
34+
delete mProgram;
35+
}
36+
37+
Process* ProcessManager::getBuildStep() {
38+
return mBuildStep;
39+
}
40+
41+
Process* ProcessManager::getProgram() {
42+
return mProgram;
43+
}
44+
45+
bool ProcessManager::runBuild() {
46+
if(mBuildStep->runAndWait())
47+
{
48+
LOG(logger, SUCCESS, "Successfully ran command");
49+
return true;
50+
}
51+
else
52+
{
53+
LOG(logger, ERROR, "A command failed to run :(");
54+
return false;
55+
}
56+
}
57+
58+
bool ProcessManager::runProcesses() {
59+
for(Process* proc : mProcesses)
60+
{
61+
if(proc->runAndWait())
62+
{
63+
LOG(logger, SUCCESS, "Successfully ran command");
64+
}
65+
else
66+
{
67+
LOG(logger, ERROR, "A command failed to run :(");
68+
}
69+
}
70+
return true;
71+
}
72+
73+
void ProcessManager::haltConstructionProcs() {
74+
for(Process* proc : mProcesses)
75+
{
76+
proc->kill();
77+
}
78+
}
79+
80+
void ProcessManager::killAll() {
81+
mBuildStep->kill();
82+
haltConstructionProcs();
83+
mProgram->kill();
84+
}
85+
86+
void ProcessManager::startProgram() {
87+
mProgram->run();
88+
}
89+
90+
void ProcessManager::haltProgram() {
91+
mProgram->kill();
92+
}
93+
94+
void ProcessManager::restartAll()
95+
{
96+
haltConstructionProcs();
97+
if(runBuild()) {
98+
runProcesses();
99+
haltProgram();
100+
startProgram();
101+
}
102+
}
103+
104+
void ProcessManager::setBuilder(Process* proc) {
105+
if(mBuildStep)
106+
throw std::runtime_error("Build Step already set");
107+
mBuildStep = proc;
108+
}
109+
110+
void ProcessManager::addProcess(Process* proc) {
111+
mProcesses.push_back(proc);
112+
}
113+
114+
void ProcessManager::setProgram(Process* proc) {
115+
if(mProgram)
116+
throw std::runtime_error("Pogram already set");
117+
mProgram = proc;
118+
}
119+

src/procman.hpp

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
/*
2+
* Renzoku - Re-build, re-test, and re-run a program whenever the code changes
3+
* Copyright (C) 2015 Colton Wolkins
4+
*
5+
* This library is free software; you can redistribute it and/or
6+
* modify it under the terms of the GNU Lesser General Public
7+
* License as published by the Free Software Foundation; either
8+
* version 2.1 of the License, or (at your option) any later version.
9+
*
10+
* This library is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13+
* Lesser General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Lesser General Public
16+
* License along with this library; if not, write to the Free Software
17+
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
18+
*
19+
*/
20+
#pragma once
21+
#include "process.hpp"
22+
#include "log.hpp"
23+
#include <vector>
24+
25+
class ProcessManager
26+
{
27+
private:
28+
Process* mBuildStep; // The actual build step
29+
std::vector<Process*> mProcesses; // Procs that run between build and launch
30+
Process* mProgram; // The actual program
31+
iLogger* logger;
32+
public:
33+
ProcessManager(iLogger*);
34+
~ProcessManager();
35+
Process* getBuildStep();
36+
Process* getProgram();
37+
bool runBuild();
38+
bool runProcesses();
39+
void haltConstructionProcs();
40+
void startProgram();
41+
void haltProgram();
42+
void restartAll();
43+
void killAll();
44+
void setBuilder(Process*);
45+
void addProcess(Process*);
46+
void setProgram(Process*);
47+
};

0 commit comments

Comments
 (0)