thread safety
This commit is contained in:
parent
97fc3605ce
commit
90d338f0a0
@ -1,17 +1,20 @@
|
||||
#include "mail.h"
|
||||
#include <mutex>
|
||||
|
||||
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()
|
||||
{}
|
||||
|
||||
/*
|
||||
|
||||
@ -37,4 +37,6 @@ struct mail {
|
||||
json mailToJson();
|
||||
|
||||
void remove();
|
||||
|
||||
std::mutex m_file;
|
||||
};
|
||||
@ -14,6 +14,7 @@
|
||||
#include <cctype>
|
||||
#include <algorithm>
|
||||
#include <future>
|
||||
#include <mutex>
|
||||
#include <pthread.h>
|
||||
#include <string_view>
|
||||
#include <sstream>
|
||||
@ -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<std::thread> 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<std::string>& received)
|
||||
mail->deleted)
|
||||
return "ERR\n";
|
||||
|
||||
try {
|
||||
/*try */{
|
||||
std::string path_str = user_handler::getInstance().getSpoolDir()/"messages"/mail->filename;
|
||||
std::lock_guard<std::mutex> 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;
|
||||
}
|
||||
|
||||
@ -4,6 +4,7 @@
|
||||
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <ostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -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<std::mutex> 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<std::string> recipients)
|
||||
{
|
||||
std::lock_guard<std::mutex> guard(this->m);
|
||||
|
||||
std::vector<user*> 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<std::mutex> guard(this->m);
|
||||
|
||||
maillist::iterator it = std::find_if(this->inbox.begin(), this->inbox.end(), [id](auto& i){ return (*i)(id); });
|
||||
|
||||
bool success = true;
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include "mail.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <vector>
|
||||
@ -37,4 +38,6 @@ private:
|
||||
std::string name;
|
||||
maillist inbox;
|
||||
maillist sent;
|
||||
|
||||
std::mutex m;
|
||||
};
|
||||
@ -4,7 +4,7 @@
|
||||
#include <filesystem>
|
||||
#include <string>
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
@ -2,6 +2,7 @@
|
||||
|
||||
#include <filesystem>
|
||||
#include <map>
|
||||
#include <mutex>
|
||||
#include <string>
|
||||
|
||||
class user;
|
||||
@ -38,4 +39,6 @@ protected:
|
||||
fs::path spool_dir;
|
||||
std::map<std::string, user*> users;
|
||||
|
||||
std::mutex m_user;
|
||||
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user