From 90d338f0a00816954257a65ac83b93a78435e568 Mon Sep 17 00:00:00 2001 From: Benedikt Galbavy Date: Wed, 15 Nov 2023 18:06:42 +0100 Subject: [PATCH] thread safety --- server/mail.cpp | 7 +++++-- server/mail.h | 2 ++ server/server.cpp | 21 ++++++++++++++------- server/user.cpp | 12 ++++++++++-- server/user.h | 3 +++ server/user_handler.cpp | 15 ++++++++++----- server/user_handler.h | 3 +++ 7 files changed, 47 insertions(+), 16 deletions(-) diff --git a/server/mail.cpp b/server/mail.cpp index 4921a4c..f3809bd 100644 --- a/server/mail.cpp +++ b/server/mail.cpp @@ -1,17 +1,20 @@ #include "mail.h" +#include mail::mail(std::string filename, std::string subject) : filename(filename), timestamp(std::time(NULL)), subject(subject), - deleted(false) + deleted(false), + m_file() {} mail::mail(std::string filename, int64_t timestamp, std::string subject) : filename(filename), timestamp(timestamp), subject(subject), - deleted(false) + deleted(false), + m_file() {} /* diff --git a/server/mail.h b/server/mail.h index 958d6da..3fa6382 100644 --- a/server/mail.h +++ b/server/mail.h @@ -37,4 +37,6 @@ struct mail { json mailToJson(); void remove(); + + std::mutex m_file; }; \ No newline at end of file diff --git a/server/server.cpp b/server/server.cpp index d2fbe76..e1c3081 100644 --- a/server/server.cpp +++ b/server/server.cpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -43,10 +44,12 @@ enum commands { namespace fs = std::filesystem; -int abortRequested = 0; +bool abortRequested = false; int create_socket = -1; int new_socket = -1; +std::vector threads; + void printUsage(); inline bool isInteger(const std::string & s); bool ichar_equals(char a, char b); @@ -166,8 +169,7 @@ int main (int argc, char* argv[]) inet_ntoa(cliaddress.sin_addr), ntohs(cliaddress.sin_port)); // clientCommunication(&new_socket); // returnValue can be ignored - std::thread th(clientCommunication, new_socket); - th.detach(); + threads.emplace_back(clientCommunication, new_socket); new_socket = -1; } @@ -305,7 +307,7 @@ void signalHandler(int sig) { if (sig == SIGINT) { printf("abort Requested... "); // ignore error - abortRequested = 1; + abortRequested = true; if (new_socket != -1) { if (shutdown(new_socket, SHUT_RDWR) == -1) @@ -363,6 +365,10 @@ std::string getSha1(const std::string& str) inline void exiting() { + for (auto& thread : threads) { + thread.join(); + } + user_handler::getInstance().saveAll(); printf("Saving... \n"); } @@ -420,13 +426,14 @@ std::string cmdREAD(std::vector& received) mail->deleted) return "ERR\n"; - try { + /*try */{ std::string path_str = user_handler::getInstance().getSpoolDir()/"messages"/mail->filename; + std::lock_guard guard(mail->m_file); response.append(read_file(path_str)).append("\n"); } - catch (...) { // TODO: more specific error handling - then again, it will respond with ERR either way + /*catch (...) { // TODO: more specific error handling - then again, it will respond with ERR either way return "ERR\n"; - } + }*/ return response; } diff --git a/server/user.cpp b/server/user.cpp index 8a27843..62d4900 100644 --- a/server/user.cpp +++ b/server/user.cpp @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -11,7 +12,7 @@ using json = nlohmann::json; -user::user(fs::path user_data_json) +user::user(fs::path user_data_json) : m() { std::ifstream ifs(user_data_json); json user_data = json::parse(ifs); @@ -50,7 +51,8 @@ user::user(fs::path user_data_json) } user::user(std::string name, fs::path user_dir) - : name(name) + : name(name), + m() { json user; user["mails"]["sent"] = json::object(); @@ -69,6 +71,8 @@ user::~user() { void user::addMail(mail* mail) { + std::lock_guard guard(this->m); + mail->id = this->inbox.size(); this->inbox.insert(mail); @@ -77,6 +81,8 @@ void user::addMail(mail* mail) void user::sendMail(mail* mail, std::vector recipients) { + std::lock_guard guard(this->m); + std::vector users; for ( auto& name : recipients) { // TODO: error handling for non existing user @@ -104,6 +110,8 @@ mail* user::getMail(u_int id) bool user::delMail(u_int id) { + std::lock_guard guard(this->m); + maillist::iterator it = std::find_if(this->inbox.begin(), this->inbox.end(), [id](auto& i){ return (*i)(id); }); bool success = true; diff --git a/server/user.h b/server/user.h index 8743843..4fcea74 100644 --- a/server/user.h +++ b/server/user.h @@ -2,6 +2,7 @@ #include "mail.h" +#include #include #include #include @@ -37,4 +38,6 @@ private: std::string name; maillist inbox; maillist sent; + + std::mutex m; }; \ No newline at end of file diff --git a/server/user_handler.cpp b/server/user_handler.cpp index 7321e01..911f8ae 100644 --- a/server/user_handler.cpp +++ b/server/user_handler.cpp @@ -4,7 +4,7 @@ #include #include -user_handler::user_handler() +user_handler::user_handler() : m_user() { for (const auto& entry : fs::directory_iterator()) { if (entry.path().extension() == ".json") { @@ -21,26 +21,31 @@ user_handler::~user_handler() user* user_handler::getUser(std::string name) { if (this->users.find(name) == this->users.end()) { + this->m_user.lock(); // avoid race condition of two threads creating the same user if (!fs::exists(this->spool_dir/"users"/(name+".json"))) return nullptr; - this->users[name] = new user(this->spool_dir/"users"/(name+".json")); + this->users.insert({name, new user(this->spool_dir/"users"/(name+".json"))}); + this->m_user.unlock(); } - return this->users[name]; + return (*this->users.find(name)).second; } user* user_handler::getOrCreateUser(std::string name) { if (this->users.find(name) == this->users.end()) { - this->users[name] = fs::exists(this->spool_dir/"users"/(name+".json")) ? + this->m_user.lock(); + this->users.insert({name, fs::exists(this->spool_dir/"users"/(name+".json")) ? new user(this->spool_dir/"users"/(name+".json")) : - new user(name, this->spool_dir/"users"); + new user(name, this->spool_dir/"users")}); + this->m_user.unlock(); } return this->users[name]; } void user_handler::saveAll() { + // will only be called from main for ( auto& user : this->users ) { user.second->saveToFile(); } diff --git a/server/user_handler.h b/server/user_handler.h index 0468d74..c19464f 100644 --- a/server/user_handler.h +++ b/server/user_handler.h @@ -2,6 +2,7 @@ #include #include +#include #include class user; @@ -37,5 +38,7 @@ protected: fs::path spool_dir; std::map users; + + std::mutex m_user; }; \ No newline at end of file