summaryrefslogtreecommitdiff
path: root/bin
diff options
context:
space:
mode:
authorChris Wilson <chris+github@qwirx.com>2006-08-09 17:53:34 +0000
committerChris Wilson <chris+github@qwirx.com>2006-08-09 17:53:34 +0000
commite7103096b1b6c9f0e90dd0c884d81957c9d7bec3 (patch)
tree48d8e827e0546257fac4c4a1f8cf451c729632ae /bin
parent753960ecd7f89708431fee9565d2d6fd3235e710 (diff)
* bin/bbackupd/BackupDaemon.cpp
- Reverted to trunk
Diffstat (limited to 'bin')
-rw-r--r--bin/bbackupd/BackupDaemon.cpp282
1 files changed, 79 insertions, 203 deletions
diff --git a/bin/bbackupd/BackupDaemon.cpp b/bin/bbackupd/BackupDaemon.cpp
index e2d7c5e7..ebf5a1ea 100644
--- a/bin/bbackupd/BackupDaemon.cpp
+++ b/bin/bbackupd/BackupDaemon.cpp
@@ -125,29 +125,6 @@ BackupDaemon::BackupDaemon()
}
#ifdef WIN32
- // Create the event object to signal from main thread to worker
- // when new messages are queued to be sent to the command socket.
- mhMessageToSendEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (mhMessageToSendEvent == INVALID_HANDLE_VALUE)
- {
- syslog(LOG_ERR, "Failed to create event object: error %d",
- GetLastError);
- exit(1);
- }
-
- // Create the event object to signal from worker to main thread
- // when a command has been received on the command socket.
- mhCommandReceivedEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (mhCommandReceivedEvent == INVALID_HANDLE_VALUE)
- {
- syslog(LOG_ERR, "Failed to create event object: error %d",
- GetLastError);
- exit(1);
- }
-
- // Create the critical section to protect the message queue
- InitializeCriticalSection(&mMessageQueueLock);
-
// Create a thread to handle the named pipe
HANDLE hThread;
unsigned int dwThreadId;
@@ -286,34 +263,15 @@ void BackupDaemon::DeleteAllLocations()
void BackupDaemon::RunHelperThread(void)
{
mpCommandSocketInfo = new CommandSocketInfo;
- WinNamedPipeStream& rSocket(mpCommandSocketInfo->mListeningSocket);
+ this->mReceivedCommandConn = false;
// loop until the parent process exits
- while (!IsTerminateWanted())
+ while (TRUE)
{
try
{
- rSocket.Accept(BOX_NAMED_PIPE_NAME);
- }
- catch (BoxException &e)
- {
- ::syslog(LOG_ERR, "Failed to open command socket: %s",
- e.what());
- SetTerminateWanted();
- break; // this is fatal
- }
- catch (...)
- {
- ::syslog(LOG_ERR, "Failed to open command socket: "
- "unknown error");
- SetTerminateWanted();
- break; // this is fatal
- }
-
- try
- {
- // Errors here do not kill the thread,
- // only the current connection.
+ mpCommandSocketInfo->mListeningSocket.Accept(
+ BOX_NAMED_PIPE_NAME);
// This next section comes from Ben's original function
// Log
@@ -331,72 +289,17 @@ void BackupDaemon::RunHelperThread(void)
conf.GetKeyValueInt("MaxUploadWait"),
mState);
- rSocket.Write(summary, summarySize);
- rSocket.Write("ping\n", 5);
-
- // old queued messages are not useful
- EnterCriticalSection(&mMessageQueueLock);
- mMessageList.clear();
- ResetEvent(mhMessageToSendEvent);
- LeaveCriticalSection(&mMessageQueueLock);
+ mpCommandSocketInfo->mListeningSocket.Write(summary, summarySize);
+ mpCommandSocketInfo->mListeningSocket.Write("ping\n", 5);
- IOStreamGetLine readLine(rSocket);
+ IOStreamGetLine readLine(mpCommandSocketInfo->mListeningSocket);
std::string command;
- while (rSocket.IsConnected() && !IsTerminateWanted())
+ while (mpCommandSocketInfo->mListeningSocket.IsConnected() &&
+ readLine.GetLine(command) )
{
- HANDLE handles[2];
- handles[0] = mhMessageToSendEvent;
- handles[1] = rSocket.GetReadableEvent();
-
- DWORD result = WaitForMultipleObjects(
- sizeof(handles)/sizeof(*handles),
- handles, FALSE, 1000);
-
- if (result == 0)
- {
- ResetEvent(mhMessageToSendEvent);
-
- EnterCriticalSection(&mMessageQueueLock);
- try
- {
- while (mMessageList.size() > 0)
- {
- std::string message = *(mMessageList.begin());
- mMessageList.erase(mMessageList.begin());
- printf("Sending '%s' to waiting client... ", message.c_str());
- message += "\n";
- rSocket.Write(message.c_str(),
- message.length());
-
- printf("done.\n");
- }
- }
- catch (...)
- {
- LeaveCriticalSection(&mMessageQueueLock);
- throw;
- }
- LeaveCriticalSection(&mMessageQueueLock);
- continue;
- }
- else if (result == WAIT_TIMEOUT)
- {
- continue;
- }
- else if (result != 1)
- {
- ::syslog(LOG_ERR, "WaitForMultipleObjects returned invalid result %d", result);
- continue;
- }
-
- if (!readLine.GetLine(command))
- {
- ::syslog(LOG_ERR, "Failed to read line");
- continue;
- }
-
- printf("Received command '%s' from client\n", command.c_str());
+ TRACE1("Receiving command '%s' over "
+ "command socket\n", command.c_str());
bool sendOK = false;
bool sendResponse = true;
@@ -435,18 +338,12 @@ void BackupDaemon::RunHelperThread(void)
SetTerminateWanted();
sendOK = true;
}
- else
- {
- ::syslog(LOG_ERR, "Received unknown command '%s' from client", command.c_str());
- sendResponse = true;
- sendOK = false;
- }
// Send a response back?
if (sendResponse)
{
const char* response = sendOK ? "ok\n" : "error\n";
- rSocket.Write(
+ mpCommandSocketInfo->mListeningSocket.Write(
response, strlen(response));
}
@@ -455,10 +352,10 @@ void BackupDaemon::RunHelperThread(void)
break;
}
- // this->mReceivedCommandConn = true;
+ this->mReceivedCommandConn = true;
}
- rSocket.Close();
+ mpCommandSocketInfo->mListeningSocket.Close();
}
catch (BoxException &e)
{
@@ -607,8 +504,8 @@ void BackupDaemon::Run2()
BackupClientContext::ClientStoreMarker_NotKnown;
// haven't contacted the store yet
- bool deleteStoreObjectInfoFile = DeserializeStoreObjectInfo(
- clientStoreMarker, lastSyncTime, nextSyncTime);
+ bool deserialised = DeserializeStoreObjectInfo(clientStoreMarker,
+ lastSyncTime, nextSyncTime);
// --------------------------------------------------------------------------------------------
@@ -714,8 +611,7 @@ void BackupDaemon::Run2()
// Delete the serialised store object file,
// so that we don't try to reload it after a
// partially completed backup
- if(deleteStoreObjectInfoFile &&
- !DeleteStoreObjectInfo())
+ if(deserialised && !DeleteStoreObjectInfo())
{
::syslog(LOG_ERR, "Failed to delete the "
"StoreObjectInfoFile, backup cannot "
@@ -725,11 +621,6 @@ void BackupDaemon::Run2()
::sleep(60);
continue;
}
-
- // In case the backup throws an exception,
- // we should not try to delete the store info
- // object file again.
- deleteStoreObjectInfoFile = false;
// Do sync
bool errorOccurred = false;
@@ -838,14 +729,8 @@ void BackupDaemon::Run2()
// --------------------------------------------------------------------------------------------
- // We had a successful backup, save the store
- // info. If we save successfully, we must
- // delete the file next time we start a backup
-
- deleteStoreObjectInfoFile =
- SerializeStoreObjectInfo(
- clientStoreMarker,
- lastSyncTime, nextSyncTime);
+ // We had a successful backup, save the store info
+ SerializeStoreObjectInfo(clientStoreMarker, lastSyncTime, nextSyncTime);
// --------------------------------------------------------------------------------------------
}
@@ -1017,27 +902,25 @@ int BackupDaemon::UseScriptToSeeIfSyncAllowed()
void BackupDaemon::WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFlagOut, bool &SyncIsForcedOut)
{
#ifdef WIN32
- DWORD requiredDelayMs = BoxTimeToMilliSeconds(RequiredDelay);
-
- DWORD result = WaitForSingleObject(mhCommandReceivedEvent,
- (DWORD)requiredDelayMs);
+ // Really could use some interprocess protection, mutex etc
+ // any side effect should be too bad???? :)
+ DWORD timeout = (DWORD)BoxTimeToMilliSeconds(RequiredDelay);
- if (result == WAIT_OBJECT_0)
- {
- DoSyncFlagOut = this->mDoSyncFlagOut;
- SyncIsForcedOut = this->mSyncIsForcedOut;
- ResetEvent(mhCommandReceivedEvent);
- }
- else if (result == WAIT_TIMEOUT)
+ while ( this->mReceivedCommandConn == false )
{
- DoSyncFlagOut = false;
- SyncIsForcedOut = false;
- }
- else
- {
- ::syslog(LOG_ERR, "Unexpected result from "
- "WaitForSingleObject: error %d", GetLastError());
+ Sleep(1);
+
+ if ( timeout == 0 )
+ {
+ DoSyncFlagOut = false;
+ SyncIsForcedOut = false;
+ return;
+ }
+ timeout--;
}
+ this->mReceivedCommandConn = false;
+ DoSyncFlagOut = this->mDoSyncFlagOut;
+ SyncIsForcedOut = this->mSyncIsForcedOut;
return;
#else // ! WIN32
@@ -1070,7 +953,7 @@ void BackupDaemon::WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFla
{
#ifdef PLATFORM_CANNOT_FIND_PEER_UID_OF_UNIX_SOCKET
bool uidOK = true;
- ::syslog(LOG_WARNING, "On this platform, no security check can be made on the credentials of peers connecting to the command socket. (bbackupctl)");
+ ::syslog(LOG_WARNING, "On this platform, no security check can be made on the credientials of peers connecting to the command socket. (bbackupctl)");
#else
// Security check -- does the process connecting to this socket have
// the same UID as this process?
@@ -1140,13 +1023,8 @@ void BackupDaemon::WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFla
while(mpCommandSocketInfo->mpGetLine != 0 && !mpCommandSocketInfo->mpGetLine->IsEOF()
&& mpCommandSocketInfo->mpGetLine->GetLine(command, false /* no preprocessing */, timeout))
{
- TRACE1("Receiving command '%s' over command socket\n",
- command.c_str());
-
- #ifdef WIN32
- SetEvent(mhCommandReceivedEvent);
- #endif
-
+ TRACE1("Receiving command '%s' over command socket\n", command.c_str());
+
bool sendOK = false;
bool sendResponse = true;
@@ -1259,8 +1137,12 @@ void BackupDaemon::CloseCommandConnection()
// --------------------------------------------------------------------------
void BackupDaemon::SendSyncStartOrFinish(bool SendStart)
{
- // The bbackupctl program can't rely on a state change, because it
- // may never change if the server doesn't need to be contacted.
+ // The bbackupctl program can't rely on a state change, because it may never
+ // change if the server doesn't need to be contacted.
+
+#ifdef __MINGW32__
+#warning race condition: what happens if socket is closed?
+#endif
if (mpCommandSocketInfo != NULL &&
#ifdef WIN32
@@ -1270,18 +1152,15 @@ void BackupDaemon::SendSyncStartOrFinish(bool SendStart)
#endif
)
{
- std::string message = SendStart ? "start-sync" : "finish-sync";
+ const char* message = SendStart ? "start-sync\n" : "finish-sync\n";
try
{
#ifdef WIN32
- EnterCriticalSection(&mMessageQueueLock);
- mMessageList.push_back(message);
- SetEvent(mhMessageToSendEvent);
- LeaveCriticalSection(&mMessageQueueLock);
+ mpCommandSocketInfo->mListeningSocket.Write(message,
+ (int)strlen(message));
#else
- message += "\n";
- mpCommandSocketInfo->mpConnectedSocket->Write(
- message.c_str(), message.size());
+ mpCommandSocketInfo->mpConnectedSocket->Write(message,
+ strlen(message));
#endif
}
catch(...)
@@ -1877,36 +1756,39 @@ void BackupDaemon::SetState(int State)
// command socket if there's an error
char newState[64];
- sprintf(newState, "state %d", State);
- std::string message = newState;
+ char newStateSize = sprintf(newState, "state %d\n", State);
#ifdef WIN32
- EnterCriticalSection(&mMessageQueueLock);
- mMessageList.push_back(newState);
- SetEvent(mhMessageToSendEvent);
- LeaveCriticalSection(&mMessageQueueLock);
-#else
- message += "\n";
-
- if(mpCommandSocketInfo == 0)
- {
- return;
- }
+ #ifndef _MSC_VER
+ #warning FIX ME: race condition
+ #endif
- if (mpCommandSocketInfo->mpConnectedSocket.get() == 0)
+ // what happens if the socket is closed by the other thread before
+ // we can write to it? Null pointer deref at best.
+ if (mpCommandSocketInfo &&
+ mpCommandSocketInfo->mListeningSocket.IsConnected())
{
- return;
- }
-
- // Something connected to the command socket, tell it about the new state
- try
- {
- mpCommandSocketInfo->mpConnectedSocket->Write(message.c_str(),
- message.length());
+ try
+ {
+ mpCommandSocketInfo->mListeningSocket.Write(newState, newStateSize);
+ }
+ catch(...)
+ {
+ CloseCommandConnection();
+ }
}
- catch(...)
+#else
+ if(mpCommandSocketInfo != 0 && mpCommandSocketInfo->mpConnectedSocket.get() != 0)
{
- CloseCommandConnection();
+ // Something connected to the command socket, tell it about the new state
+ try
+ {
+ mpCommandSocketInfo->mpConnectedSocket->Write(newState, newStateSize);
+ }
+ catch(...)
+ {
+ CloseCommandConnection();
+ }
}
#endif
}
@@ -2291,11 +2173,11 @@ static const int STOREOBJECTINFO_MAGIC_ID_VALUE = 0x7777525F;
static const std::string STOREOBJECTINFO_MAGIC_ID_STRING = "BBACKUPD-STATE";
static const int STOREOBJECTINFO_VERSION = 1;
-bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const
+void BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time_t theLastSyncTime, box_time_t theNextSyncTime) const
{
if(!GetConfiguration().KeyExists("StoreObjectInfoFile"))
{
- return false;
+ return;
}
std::string StoreObjectInfoFile =
@@ -2303,17 +2185,13 @@ bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time
if (StoreObjectInfoFile.size() <= 0)
{
- return false;
+ return;
}
- bool created = false;
-
try
{
FileStream aFile(StoreObjectInfoFile.c_str(),
O_WRONLY | O_CREAT | O_TRUNC);
- created = true;
-
Archive anArchive(aFile, 0);
anArchive.Write(STOREOBJECTINFO_MAGIC_ID_VALUE);
@@ -2358,8 +2236,6 @@ bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time
"not accessible or could not be created",
StoreObjectInfoFile.c_str());
}
-
- return created;
}
// --------------------------------------------------------------------------