From 264ef04ecb8668b21df8539e3a807d3f266a1780 Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Sat, 14 Oct 2006 14:44:23 +0000 Subject: * Oops, svn merged too much, undo again --- bin/bbackupd/BackupDaemon.cpp | 300 +++++++++++++++--------------------------- 1 file changed, 105 insertions(+), 195 deletions(-) (limited to 'bin') diff --git a/bin/bbackupd/BackupDaemon.cpp b/bin/bbackupd/BackupDaemon.cpp index d6f4b7f4..99abb01f 100644 --- a/bin/bbackupd/BackupDaemon.cpp +++ b/bin/bbackupd/BackupDaemon.cpp @@ -59,7 +59,6 @@ #include "BackupStoreFilenameClear.h" #include "BackupClientInodeToIDMap.h" #include "autogen_BackupProtocolClient.h" -#include "autogen_ConversionException.h" #include "BackupClientCryptoKeys.h" #include "BannerText.h" #include "BackupStoreFile.h" @@ -126,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,6 +262,7 @@ void BackupDaemon::DeleteAllLocations() #ifdef WIN32 void BackupDaemon::RunHelperThread(void) { + this->mReceivedCommandConn = false; mpCommandSocketInfo = new CommandSocketInfo; WinNamedPipeStream& rSocket(mpCommandSocketInfo->mListeningSocket); @@ -351,69 +328,15 @@ void BackupDaemon::RunHelperThread(void) rSocket.Write(summary, summarySize); rSocket.Write("ping\n", 5); - // old queued messages are not useful - EnterCriticalSection(&mMessageQueueLock); - mMessageList.clear(); - ResetEvent(mhMessageToSendEvent); - LeaveCriticalSection(&mMessageQueueLock); - IOStreamGetLine readLine(rSocket); std::string command; - while (rSocket.IsConnected() && !IsTerminateWanted()) + while (rSocket.IsConnected() && + readLine.GetLine(command) && + !IsTerminateWanted()) { - 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("Received command '%s' over " + "command socket\n", command.c_str()); bool sendOK = false; bool sendResponse = true; @@ -432,7 +355,6 @@ void BackupDaemon::RunHelperThread(void) this->mDoSyncFlagOut = true; this->mSyncIsForcedOut = false; sendOK = true; - SetEvent(mhCommandReceivedEvent); } else if(command == "force-sync") { @@ -440,21 +362,18 @@ void BackupDaemon::RunHelperThread(void) this->mDoSyncFlagOut = true; this->mSyncIsForcedOut = true; sendOK = true; - SetEvent(mhCommandReceivedEvent); } else if(command == "reload") { // Reload the configuration SetReloadConfigWanted(); sendOK = true; - SetEvent(mhCommandReceivedEvent); } else if(command == "terminate") { // Terminate the daemon cleanly SetTerminateWanted(); sendOK = true; - SetEvent(mhCommandReceivedEvent); } else { @@ -464,17 +383,19 @@ void BackupDaemon::RunHelperThread(void) } // Send a response back? - if(sendResponse) + if (sendResponse) { const char* response = sendOK ? "ok\n" : "error\n"; rSocket.Write( response, strlen(response)); } - if(disconnect) + if (disconnect) { break; } + + this->mReceivedCommandConn = true; } rSocket.Close(); @@ -494,9 +415,6 @@ void BackupDaemon::RunHelperThread(void) ::syslog(LOG_ERR, "Communication error with control client"); } } - - CloseHandle(mhCommandReceivedEvent); - CloseHandle(mhMessageToSendEvent); } #endif @@ -1016,21 +934,8 @@ int BackupDaemon::UseScriptToSeeIfSyncAllowed() } else { - try - { - // How many seconds to wait? - waitInSeconds = BoxConvert::Convert(line); - } - catch(ConversionException &e) - { - ::syslog(LOG_ERR, "Invalid output " - "from SyncAllowScript '%s': " - "'%s'", - conf.GetKeyValue("SyncAllowScript").c_str(), - line.c_str()); - throw; - } - + // How many seconds to wait? + waitInSeconds = BoxConvert::Convert(line); ::syslog(LOG_INFO, "Delaying sync by %d seconds (SyncAllowScript '%s')", waitInSeconds, conf.GetKeyValue("SyncAllowScript").c_str()); } } @@ -1049,7 +954,7 @@ int BackupDaemon::UseScriptToSeeIfSyncAllowed() } // Wait and then cleanup child process, if any - if(pid != 0) + if (pid != 0) { int status = 0; ::waitpid(pid, &status, 0); @@ -1072,27 +977,25 @@ int BackupDaemon::UseScriptToSeeIfSyncAllowed() void BackupDaemon::WaitOnCommandSocket(box_time_t RequiredDelay, bool &DoSyncFlagOut, bool &SyncIsForcedOut) { #ifdef WIN32 - DWORD requiredDelayMs = BoxTimeToMilliSeconds(RequiredDelay); + // Really could use some interprocess protection, mutex etc + // any side effect should be too bad???? :) + DWORD timeout = (DWORD)BoxTimeToMilliSeconds(RequiredDelay); - DWORD result = WaitForSingleObject(mhCommandReceivedEvent, - (DWORD)requiredDelayMs); - - if(result == WAIT_OBJECT_0) - { - DoSyncFlagOut = this->mDoSyncFlagOut; - SyncIsForcedOut = this->mSyncIsForcedOut; - ResetEvent(mhCommandReceivedEvent); - } - else if(result == WAIT_TIMEOUT) - { - DoSyncFlagOut = false; - SyncIsForcedOut = false; - } - else + while ( this->mReceivedCommandConn == false ) { - ::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 @@ -1195,9 +1098,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()); - + TRACE1("Receiving command '%s' over command socket\n", command.c_str()); + bool sendOK = false; bool sendResponse = true; @@ -1334,7 +1236,11 @@ 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. - if(mpCommandSocketInfo != NULL && +#ifdef __MINGW32__ +#warning race condition: what happens if socket is closed? +#endif + + if (mpCommandSocketInfo != NULL && #ifdef WIN32 mpCommandSocketInfo->mListeningSocket.IsConnected() #else @@ -1342,18 +1248,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(std::exception &e) @@ -1955,36 +1858,51 @@ 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; - } - - if(mpCommandSocketInfo->mpConnectedSocket.get() == 0) - { - return; - } + #ifndef _MSC_VER + #warning FIX ME: race condition + #endif - // Something connected to the command socket, tell it about the new state - try + // 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()) { - mpCommandSocketInfo->mpConnectedSocket->Write(message.c_str(), - message.length()); + try + { + mpCommandSocketInfo->mListeningSocket.Write(newState, newStateSize); + } + catch(std::exception &e) + { + ::syslog(LOG_ERR, "Internal error while writing state " + "to command socket: %s", e.what()); + CloseCommandConnection(); + } + 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(std::exception &e) + { + ::syslog(LOG_ERR, "Internal error while writing state " + "to command socket: %s", e.what()); + CloseCommandConnection(); + } + catch(...) + { + CloseCommandConnection(); + } } #endif } @@ -2167,12 +2085,12 @@ void BackupDaemon::Location::Deserialize(Archive &rArchive) // // mpDirectoryRecord.reset(NULL); - if(mpExcludeFiles) + if (mpExcludeFiles) { delete mpExcludeFiles; mpExcludeFiles = NULL; } - if(mpExcludeDirs) + if (mpExcludeDirs) { delete mpExcludeDirs; mpExcludeDirs = NULL; @@ -2191,17 +2109,15 @@ void BackupDaemon::Location::Deserialize(Archive &rArchive) int64_t aMagicMarker = 0; rArchive.Read(aMagicMarker); - if(aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP) + if (aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP) { // NOOP } - else if(aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE) + else if (aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE) { BackupClientDirectoryRecord *pSubRecord = new BackupClientDirectoryRecord(0, ""); - if(!pSubRecord) - { + if (!pSubRecord) throw std::bad_alloc(); - } mpDirectoryRecord.reset(pSubRecord); mpDirectoryRecord->Deserialize(rArchive); @@ -2217,17 +2133,15 @@ void BackupDaemon::Location::Deserialize(Archive &rArchive) // rArchive.Read(aMagicMarker); - if(aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP) + if (aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP) { // NOOP } - else if(aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE) + else if (aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE) { mpExcludeFiles = new ExcludeList; - if(!mpExcludeFiles) - { + if (!mpExcludeFiles) throw std::bad_alloc(); - } mpExcludeFiles->Deserialize(rArchive); } @@ -2242,17 +2156,15 @@ void BackupDaemon::Location::Deserialize(Archive &rArchive) // rArchive.Read(aMagicMarker); - if(aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP) + if (aMagicMarker == ARCHIVE_MAGIC_VALUE_NOOP) { // NOOP } - else if(aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE) + else if (aMagicMarker == ARCHIVE_MAGIC_VALUE_RECURSE) { mpExcludeDirs = new ExcludeList; - if(!mpExcludeDirs) - { + if (!mpExcludeDirs) throw std::bad_alloc(); - } mpExcludeDirs->Deserialize(rArchive); } @@ -2284,7 +2196,7 @@ void BackupDaemon::Location::Serialize(Archive & rArchive) const // // // - if(mpDirectoryRecord.get() == NULL) + if (mpDirectoryRecord.get() == NULL) { int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_NOOP; rArchive.Write(aMagicMarker); @@ -2300,7 +2212,7 @@ void BackupDaemon::Location::Serialize(Archive & rArchive) const // // // - if(!mpExcludeFiles) + if (!mpExcludeFiles) { int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_NOOP; rArchive.Write(aMagicMarker); @@ -2316,7 +2228,7 @@ void BackupDaemon::Location::Serialize(Archive & rArchive) const // // // - if(!mpExcludeDirs) + if (!mpExcludeDirs) { int64_t aMagicMarker = ARCHIVE_MAGIC_VALUE_NOOP; rArchive.Write(aMagicMarker); @@ -2385,7 +2297,7 @@ bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time std::string StoreObjectInfoFile = GetConfiguration().GetKeyValue("StoreObjectInfoFile"); - if(StoreObjectInfoFile.size() <= 0) + if (StoreObjectInfoFile.size() <= 0) { return false; } @@ -2414,7 +2326,7 @@ bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time int64_t iCount = mLocations.size(); anArchive.Write(iCount); - for(int v = 0; v < iCount; v++) + for (int v = 0; v < iCount; v++) { ASSERT(mLocations[v]); mLocations[v]->Serialize(anArchive); @@ -2426,7 +2338,7 @@ bool BackupDaemon::SerializeStoreObjectInfo(int64_t aClientStoreMarker, box_time iCount = mIDMapMounts.size(); anArchive.Write(iCount); - for(int v = 0; v < iCount; v++) + for (int v = 0; v < iCount; v++) anArchive.Write(mIDMapMounts[v]); // @@ -2479,7 +2391,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ std::string StoreObjectInfoFile = GetConfiguration().GetKeyValue("StoreObjectInfoFile"); - if(StoreObjectInfoFile.size() <= 0) + if (StoreObjectInfoFile.size() <= 0) { return false; } @@ -2495,7 +2407,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ int iMagicValue = 0; anArchive.Read(iMagicValue); - if(iMagicValue != STOREOBJECTINFO_MAGIC_ID_VALUE) + if (iMagicValue != STOREOBJECTINFO_MAGIC_ID_VALUE) { ::syslog(LOG_WARNING, "Store object info file '%s' " "is not a valid or compatible serialised " @@ -2510,7 +2422,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ std::string strMagicValue; anArchive.Read(strMagicValue); - if(strMagicValue != STOREOBJECTINFO_MAGIC_ID_STRING) + if (strMagicValue != STOREOBJECTINFO_MAGIC_ID_STRING) { ::syslog(LOG_WARNING, "Store object info file '%s' " "is not a valid or compatible serialised " @@ -2526,7 +2438,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ int iVersion = 0; anArchive.Read(iVersion); - if(iVersion != STOREOBJECTINFO_VERSION) + if (iVersion != STOREOBJECTINFO_VERSION) { ::syslog(LOG_WARNING, "Store object info file '%s' " "version %d unsupported. " @@ -2543,7 +2455,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ box_time_t lastKnownConfigModTime; anArchive.Read(lastKnownConfigModTime); - if(lastKnownConfigModTime != GetLoadedConfigModifiedTime()) + if (lastKnownConfigModTime != GetLoadedConfigModifiedTime()) { ::syslog(LOG_WARNING, "Store object info file '%s' " "out of date. Will re-cache from store", @@ -2564,13 +2476,11 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ int64_t iCount = 0; anArchive.Read(iCount); - for(int v = 0; v < iCount; v++) + for (int v = 0; v < iCount; v++) { Location* pLocation = new Location; - if(!pLocation) - { + if (!pLocation) throw std::bad_alloc(); - } pLocation->Deserialize(anArchive); mLocations.push_back(pLocation); @@ -2582,7 +2492,7 @@ bool BackupDaemon::DeserializeStoreObjectInfo(int64_t & aClientStoreMarker, box_ iCount = 0; anArchive.Read(iCount); - for(int v = 0; v < iCount; v++) + for (int v = 0; v < iCount; v++) { std::string strItem; anArchive.Read(strItem); -- cgit v1.2.3