Przeglądaj źródła

Fixed potential race condition where the ExecutiveProcess might send a notification message through cout while the OutputProcessor was busy using cout also. The result would be (at best) corrupted output. Now the ExecutiveProcess and the OutputProcessor both use OutputProcessor::sendString() which protects cout with a mutex.

git-svn-id: https://svn.microneil.com/svn/SNF4CGP/trunk@34 59e8e3e7-56fa-483b-b4b4-fa6ab0af3dfc
master
madscientist 15 lat temu
rodzic
commit
1f9713514c

+ 17
- 4
SNF4CGP/ExecutiveProcess.cpp Wyświetl plik

@@ -7,6 +7,8 @@
#include "../CodeDweller/faults.hpp"
#include <iostream>
#include <string>
#include <sstream>
using namespace std;
@@ -62,6 +64,18 @@ void ExecutiveProcess::dispatchWakeupCommand() {
dispatchCommand(C); // and dispatch a job with it.
}
void ExecutiveProcess::notifyQUIT() {
ostringstream O;
O << "* SNF4CGP[" << QuitJobNumber << "] Received QUIT, shutting down..." << endl;
Output.sendString(O.str());
}
void ExecutiveProcess::notifyNOTGOOD() {
ostringstream O;
O << "* SNF4CGP Input stream has gone bad, shutting down..." << endl;
Output.sendString(O.str());
}
void ExecutiveProcess::doProcessing() { // Command processing happens here.
dispatchWakeupCommand(); // First job is to announce ourselves.
for(;;) { // Then process all jobs but QUIT.
@@ -70,19 +84,18 @@ void ExecutiveProcess::doProcessing() {
case Command::QUIT: {
QuitJobNumber = C.Number;
cout << "* SNF4CGP[" << C.Number << "] Received QUIT, shutting down..." << endl;
cout.flush();
notifyQUIT();
return;
}
case Command::NOTGOOD: {
cout << "* SNF4CGP Input stream has gone bad, shutting down..." << endl;
cout.flush();
notifyNOTGOOD();
return;
}
default: {
dispatchCommand(C);
continue;
}
}
}

+ 3
- 0
SNF4CGP/ExecutiveProcess.hpp Wyświetl plik

@@ -41,6 +41,9 @@ class ExecutiveProcess {
void dispatchCommand(Command& C); // Job + Worker + Command; go!
void dispatchWakeupCommand();
void notifyQUIT();
void notifyNOTGOOD();
public:
ExecutiveProcess(const string& Version, const string& Config); // Simple construction. The d'tor needs

+ 7
- 2
SNF4CGP/OutputProcessor.cpp Wyświetl plik

@@ -39,6 +39,12 @@ void OutputProcessor::outputJob(Job& J) {
CompletedJobs.give(&J);
}
void OutputProcessor::sendString(const string& S) { // Safely send a string to cout.
ScopeMutex OneFlushAtATime(ProtectCout);
cout << S;
cout.flush();
}
void OutputProcessor::stop() { // Finish off the queue and quit.
if(false == isTimeToStop) { // Do this only once.
isTimeToStop = true; // Set the stop flag.
@@ -48,8 +54,7 @@ void OutputProcessor::stop() {
void OutputProcessor::handleJob(Job& J) { // Process a job.
CurrentThreadState(PostingResponses);
cout << J.Responses();
cout.flush();
sendString(J.Responses());
J.clear();
RecycledJobs().drop(J);
}

+ 3
- 0
SNF4CGP/OutputProcessor.hpp Wyświetl plik

@@ -19,6 +19,8 @@ class Job;
class OutputProcessor : private Thread { // Process job outputs.
private:
Mutex ProtectCout;
JobPool* RecycledJobs_; // Where we put our recycled jobs.
JobPool& RecycledJobs(); // Safe access to jobs pool.
ProductionQueue<Job*> CompletedJobs; // Input queue for jobs to process.
@@ -35,6 +37,7 @@ class OutputProcessor : private Thread {
void init(JobPool& J); // Start processing.
void outputJob(Job& J); // Take this job and ... you know.
void sendString(const string& S); // Safely send a string to cout.
void stop(); // Finish off the queue and quit.
const static ThreadType Type;

+ 1
- 1
SNF4CGP/main.cpp Wyświetl plik

@@ -13,7 +13,7 @@
using namespace std; // Introduce standard namespace.
const string SNF4CGP_VERSION_INFO = "SNF4CGP Version 0.0.2 Build: " __DATE__ " " __TIME__;
const string SNF4CGP_VERSION_INFO = "SNF4CGP Version 0.0.3 Build: " __DATE__ " " __TIME__;
const int ConfigPathArgNumber = 1;
const int CorrectArgcNumber = 2;

Ładowanie…
Anuluj
Zapisz