mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-05 15:48:19 +00:00
use pid in file names of temporary files
to prevent race conditions with multiple clients running when saving maps, config on quit, during upgrade
This commit is contained in:
parent
5929517941
commit
31ae4c4d5a
|
@ -38,4 +38,4 @@ $ ./find_unchanged.py ../spanish.txt
|
|||
|
||||
To update all languages:
|
||||
|
||||
$ for i in data/languages/*.txt; do scripts/languages/copy_fix.py $i $i.tmp --delete-unused --append-missing && mv $i.tmp $i; done
|
||||
$ for i in data/languages/*.txt; do scripts/languages/copy_fix.py $i $i.$$.tmp --delete-unused --append-missing && mv $i.$$.tmp $i; done
|
||||
|
|
|
@ -329,6 +329,7 @@ CClient::CClient() : m_DemoPlayer(&m_SnapshotDelta)
|
|||
m_MapDetailsSha256 = SHA256_ZEROED;
|
||||
m_MapDetailsCrc = 0;
|
||||
|
||||
str_format(m_aDDNetInfoTmp, sizeof(m_aDDNetInfoTmp), DDNET_INFO ".%d.tmp", pid());
|
||||
m_pDDNetInfoTask = NULL;
|
||||
m_aNews[0] = '\0';
|
||||
|
||||
|
@ -1492,11 +1493,21 @@ static void FormatMapDownloadFilename(const char *pName, SHA256_DIGEST *pSha256,
|
|||
sha256_str(*pSha256, aSha256 + 1, sizeof(aSha256) - 1);
|
||||
}
|
||||
|
||||
str_format(pBuffer, BufferSize, "%s_%08x%s.map%s",
|
||||
pName,
|
||||
Crc,
|
||||
aSha256,
|
||||
Temp ? ".tmp" : "");
|
||||
if(Temp)
|
||||
{
|
||||
str_format(pBuffer, BufferSize, "%s_%08x%s.map.%d.tmp",
|
||||
pName,
|
||||
Crc,
|
||||
aSha256,
|
||||
pid());
|
||||
}
|
||||
else
|
||||
{
|
||||
str_format(pBuffer, BufferSize, "%s_%08x%s.map",
|
||||
pName,
|
||||
Crc,
|
||||
aSha256);
|
||||
}
|
||||
}
|
||||
|
||||
static CServerCapabilities GetServerCapabilities(int Version, int Flags)
|
||||
|
@ -2295,7 +2306,7 @@ void CClient::ResetDDNetInfo()
|
|||
void CClient::FinishDDNetInfo()
|
||||
{
|
||||
ResetDDNetInfo();
|
||||
m_pStorage->RenameFile(DDNET_INFO_TMP, DDNET_INFO, IStorage::TYPE_SAVE);
|
||||
m_pStorage->RenameFile(m_aDDNetInfoTmp, DDNET_INFO, IStorage::TYPE_SAVE);
|
||||
LoadDDNetInfo();
|
||||
}
|
||||
|
||||
|
@ -4134,7 +4145,7 @@ void CClient::RequestDDNetInfo()
|
|||
str_append(aUrl, aEscaped, sizeof(aUrl));
|
||||
}
|
||||
|
||||
m_pDDNetInfoTask = std::make_shared<CGetFile>(Storage(), aUrl, DDNET_INFO_TMP, IStorage::TYPE_SAVE, true);
|
||||
m_pDDNetInfoTask = std::make_shared<CGetFile>(Storage(), aUrl, m_aDDNetInfoTmp, IStorage::TYPE_SAVE, true);
|
||||
Engine()->AddJob(m_pDDNetInfoTask);
|
||||
}
|
||||
|
||||
|
|
|
@ -166,6 +166,7 @@ class CClient : public IClient, public CDemoPlayer::IListener
|
|||
int m_MapDetailsCrc;
|
||||
SHA256_DIGEST m_MapDetailsSha256;
|
||||
|
||||
char m_aDDNetInfoTmp[64];
|
||||
std::shared_ptr<CGetFile> m_pDDNetInfoTask;
|
||||
|
||||
// time
|
||||
|
|
|
@ -86,6 +86,9 @@ CUpdater::CUpdater()
|
|||
m_State = CLEAN;
|
||||
m_Percent = 0;
|
||||
m_Lock = lock_create();
|
||||
|
||||
str_format(m_aClientExecTmp, sizeof(m_aClientExecTmp), CLIENT_EXEC ".%d.tmp", pid());
|
||||
str_format(m_aServerExecTmp, sizeof(m_aServerExecTmp), SERVER_EXEC ".%d.tmp", pid());
|
||||
}
|
||||
|
||||
void CUpdater::Init()
|
||||
|
@ -187,16 +190,17 @@ bool CUpdater::ReplaceClient()
|
|||
{
|
||||
dbg_msg("updater", "replacing " PLAT_CLIENT_EXEC);
|
||||
bool Success = true;
|
||||
char aPath[512];
|
||||
|
||||
// Replace running executable by renaming twice...
|
||||
if(!m_IsWinXP)
|
||||
{
|
||||
m_pStorage->RemoveBinaryFile("DDNet.old");
|
||||
Success &= m_pStorage->RenameBinaryFile(PLAT_CLIENT_EXEC, "DDNet.old");
|
||||
Success &= m_pStorage->RenameBinaryFile("update/DDNet.tmp", PLAT_CLIENT_EXEC);
|
||||
m_pStorage->RemoveBinaryFile(CLIENT_EXEC ".old");
|
||||
Success &= m_pStorage->RenameBinaryFile(PLAT_CLIENT_EXEC, CLIENT_EXEC ".old");
|
||||
str_format(aPath, sizeof(aPath), "update/%s", m_aClientExecTmp);
|
||||
Success &= m_pStorage->RenameBinaryFile(aPath, PLAT_CLIENT_EXEC);
|
||||
}
|
||||
#if !defined(CONF_FAMILY_WINDOWS)
|
||||
char aPath[512];
|
||||
m_pStorage->GetBinaryPath(PLAT_CLIENT_EXEC, aPath, sizeof aPath);
|
||||
char aBuf[512];
|
||||
str_format(aBuf, sizeof aBuf, "chmod +x %s", aPath);
|
||||
|
@ -213,13 +217,14 @@ bool CUpdater::ReplaceServer()
|
|||
{
|
||||
dbg_msg("updater", "replacing " PLAT_SERVER_EXEC);
|
||||
bool Success = true;
|
||||
char aPath[512];
|
||||
|
||||
//Replace running executable by renaming twice...
|
||||
m_pStorage->RemoveBinaryFile("DDNet-Server.old");
|
||||
Success &= m_pStorage->RenameBinaryFile(PLAT_SERVER_EXEC, "DDNet-Server.old");
|
||||
Success &= m_pStorage->RenameBinaryFile("update/DDNet-Server.tmp", PLAT_SERVER_EXEC);
|
||||
m_pStorage->RemoveBinaryFile(SERVER_EXEC ".old");
|
||||
Success &= m_pStorage->RenameBinaryFile(PLAT_SERVER_EXEC, SERVER_EXEC ".old");
|
||||
str_format(aPath, sizeof(aPath), "update/%s", m_aServerExecTmp);
|
||||
Success &= m_pStorage->RenameBinaryFile(aPath, PLAT_SERVER_EXEC);
|
||||
#if !defined(CONF_FAMILY_WINDOWS)
|
||||
char aPath[512];
|
||||
m_pStorage->GetBinaryPath(PLAT_SERVER_EXEC, aPath, sizeof aPath);
|
||||
char aBuf[512];
|
||||
str_format(aBuf, sizeof aBuf, "chmod +x %s", aPath);
|
||||
|
@ -288,13 +293,13 @@ void CUpdater::PerformUpdate()
|
|||
ParseUpdate();
|
||||
m_State = DOWNLOADING;
|
||||
|
||||
const char *aLastFile;
|
||||
aLastFile = "";
|
||||
const char *pLastFile;
|
||||
pLastFile = "";
|
||||
for(map<string, bool>::reverse_iterator it = m_FileJobs.rbegin(); it != m_FileJobs.rend(); ++it)
|
||||
{
|
||||
if(it->second)
|
||||
{
|
||||
aLastFile = it->first.c_str();
|
||||
pLastFile = it->first.c_str();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -320,7 +325,7 @@ void CUpdater::PerformUpdate()
|
|||
{
|
||||
FetchFile(pFile);
|
||||
}
|
||||
aLastFile = pFile;
|
||||
pLastFile = pFile;
|
||||
}
|
||||
else
|
||||
m_pStorage->RemoveBinaryFile(it->first.c_str());
|
||||
|
@ -328,16 +333,16 @@ void CUpdater::PerformUpdate()
|
|||
|
||||
if(m_ServerUpdate)
|
||||
{
|
||||
FetchFile(PLAT_SERVER_DOWN, "DDNet-Server.tmp");
|
||||
aLastFile = "DDNet-Server.tmp";
|
||||
FetchFile(PLAT_SERVER_DOWN, m_aServerExecTmp);
|
||||
pLastFile = m_aServerExecTmp;
|
||||
}
|
||||
if(m_ClientUpdate)
|
||||
{
|
||||
FetchFile(PLAT_CLIENT_DOWN, "DDNet.tmp");
|
||||
aLastFile = "DDNet.tmp";
|
||||
FetchFile(PLAT_CLIENT_DOWN, m_aClientExecTmp);
|
||||
pLastFile = m_aClientExecTmp;
|
||||
}
|
||||
|
||||
str_copy(m_aLastFile, aLastFile, sizeof(m_aLastFile));
|
||||
str_copy(m_aLastFile, pLastFile, sizeof(m_aLastFile));
|
||||
}
|
||||
|
||||
void CUpdater::CommitUpdate()
|
||||
|
@ -372,7 +377,7 @@ void CUpdater::WinXpRestart()
|
|||
if(!bhFile)
|
||||
return;
|
||||
char bBuf[512];
|
||||
str_format(bBuf, sizeof(bBuf), ":_R\r\ndel \"DDNet.exe\"\r\nif exist \"DDNet.exe\" goto _R\r\n:_T\r\nmove /y \"update\\DDNet.tmp\" \"DDNet.exe\"\r\nif not exist \"DDNet.exe\" goto _T\r\nstart DDNet.exe\r\ndel \"du.bat\"\r\n");
|
||||
str_format(bBuf, sizeof(bBuf), ":_R\r\ndel \"" PLAT_CLIENT_EXEC "\"\r\nif exist \"" PLAT_CLIENT_EXEC "\" goto _R\r\n:_T\r\nmove /y \"update\\%s\" \"" PLAT_CLIENT_EXEC "\"\r\nif not exist \"" PLAT_CLIENT_EXEC "\" goto _T\r\nstart " PLAT_CLIENT_EXEC "\r\ndel \"du.bat\"\r\n", m_aClientExecTmp);
|
||||
io_write(bhFile, bBuf, str_length(bBuf));
|
||||
io_close(bhFile);
|
||||
shell_execute(aBuf);
|
||||
|
|
|
@ -48,6 +48,8 @@ class CUpdater : public IUpdater
|
|||
char m_aStatus[256];
|
||||
int m_Percent;
|
||||
char m_aLastFile[256];
|
||||
char m_aClientExecTmp[64];
|
||||
char m_aServerExecTmp[64];
|
||||
|
||||
bool m_ClientUpdate;
|
||||
bool m_ServerUpdate;
|
||||
|
|
|
@ -8,7 +8,6 @@
|
|||
#include "kernel.h"
|
||||
|
||||
#define DDNET_INFO "ddnet-info.json"
|
||||
#define DDNET_INFO_TMP DDNET_INFO ".tmp"
|
||||
|
||||
/*
|
||||
Structure: CServerInfo
|
||||
|
|
|
@ -65,7 +65,10 @@ public:
|
|||
if(!m_pStorage || !g_Config.m_ClSaveSettings)
|
||||
return;
|
||||
|
||||
m_ConfigFile = m_pStorage->OpenFile(CONFIG_FILE_TMP, IOFLAG_WRITE, IStorage::TYPE_SAVE);
|
||||
char aConfigFileTmp[64];
|
||||
str_format(aConfigFileTmp, sizeof(aConfigFileTmp), CONFIG_FILE ".%d.tmp", pid());
|
||||
|
||||
m_ConfigFile = m_pStorage->OpenFile(aConfigFileTmp, IOFLAG_WRITE, IStorage::TYPE_SAVE);
|
||||
|
||||
if(!m_ConfigFile)
|
||||
return;
|
||||
|
@ -95,12 +98,12 @@ public:
|
|||
|
||||
if(m_Failed)
|
||||
{
|
||||
dbg_msg("config", "ERROR: writing to " CONFIG_FILE_TMP " failed");
|
||||
dbg_msg("config", "ERROR: writing to %s failed", aConfigFileTmp);
|
||||
return;
|
||||
}
|
||||
|
||||
if(!m_pStorage->RenameFile(CONFIG_FILE_TMP, CONFIG_FILE, IStorage::TYPE_SAVE))
|
||||
dbg_msg("config", "ERROR: renaming " CONFIG_FILE_TMP " to " CONFIG_FILE " failed");
|
||||
if(!m_pStorage->RenameFile(aConfigFileTmp, CONFIG_FILE, IStorage::TYPE_SAVE))
|
||||
dbg_msg("config", "ERROR: renaming %s to " CONFIG_FILE " failed", aConfigFileTmp);
|
||||
}
|
||||
|
||||
virtual void RegisterCallback(SAVECALLBACKFUNC pfnFunc, void *pUserData)
|
||||
|
|
|
@ -4,7 +4,6 @@
|
|||
#define ENGINE_SHARED_CONFIG_H
|
||||
|
||||
#define CONFIG_FILE "settings_ddnet.cfg"
|
||||
#define CONFIG_FILE_TMP CONFIG_FILE ".tmp"
|
||||
#define AUTOEXEC_FILE "autoexec.cfg"
|
||||
#define AUTOEXEC_CLIENT_FILE "autoexec_client.cfg"
|
||||
#define AUTOEXEC_SERVER_FILE "autoexec_server.cfg"
|
||||
|
|
|
@ -2874,7 +2874,7 @@ void CGameContext::OnMapChange(char *pNewMapName, int MapNameSize)
|
|||
char aConfig[128];
|
||||
char aTemp[128];
|
||||
str_format(aConfig, sizeof(aConfig), "maps/%s.cfg", g_Config.m_SvMap);
|
||||
str_format(aTemp, sizeof(aTemp), "%s.temp.%d", pNewMapName, pid());
|
||||
str_format(aTemp, sizeof(aTemp), "%s.%d.tmp", pNewMapName, pid());
|
||||
|
||||
IOHANDLE File = Storage()->OpenFile(aConfig, IOFLAG_READ, IStorage::TYPE_ALL);
|
||||
if(!File)
|
||||
|
|
Loading…
Reference in a new issue