diff options
author | Chris Wilson <chris+github@qwirx.com> | 2006-08-09 17:53:34 +0000 |
---|---|---|
committer | Chris Wilson <chris+github@qwirx.com> | 2006-08-09 17:53:34 +0000 |
commit | e7103096b1b6c9f0e90dd0c884d81957c9d7bec3 (patch) | |
tree | 48d8e827e0546257fac4c4a1f8cf451c729632ae /bin | |
parent | 753960ecd7f89708431fee9565d2d6fd3235e710 (diff) |
* bin/bbackupd/BackupDaemon.cpp
- Reverted to trunk
Diffstat (limited to 'bin')
-rw-r--r-- | bin/bbackupd/BackupDaemon.cpp | 282 |
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; } // -------------------------------------------------------------------------- |