thread safety
This commit is contained in:
parent
97fc3605ce
commit
90d338f0a0
@ -1,17 +1,20 @@
|
|||||||
#include "mail.h"
|
#include "mail.h"
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
mail::mail(std::string filename, std::string subject) :
|
mail::mail(std::string filename, std::string subject) :
|
||||||
filename(filename),
|
filename(filename),
|
||||||
timestamp(std::time(NULL)),
|
timestamp(std::time(NULL)),
|
||||||
subject(subject),
|
subject(subject),
|
||||||
deleted(false)
|
deleted(false),
|
||||||
|
m_file()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
mail::mail(std::string filename, int64_t timestamp, std::string subject) :
|
mail::mail(std::string filename, int64_t timestamp, std::string subject) :
|
||||||
filename(filename),
|
filename(filename),
|
||||||
timestamp(timestamp),
|
timestamp(timestamp),
|
||||||
subject(subject),
|
subject(subject),
|
||||||
deleted(false)
|
deleted(false),
|
||||||
|
m_file()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@ -37,4 +37,6 @@ struct mail {
|
|||||||
json mailToJson();
|
json mailToJson();
|
||||||
|
|
||||||
void remove();
|
void remove();
|
||||||
|
|
||||||
|
std::mutex m_file;
|
||||||
};
|
};
|
||||||
@ -14,6 +14,7 @@
|
|||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <future>
|
#include <future>
|
||||||
|
#include <mutex>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <string_view>
|
#include <string_view>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
@ -43,10 +44,12 @@ enum commands {
|
|||||||
|
|
||||||
namespace fs = std::filesystem;
|
namespace fs = std::filesystem;
|
||||||
|
|
||||||
int abortRequested = 0;
|
bool abortRequested = false;
|
||||||
int create_socket = -1;
|
int create_socket = -1;
|
||||||
int new_socket = -1;
|
int new_socket = -1;
|
||||||
|
|
||||||
|
std::vector<std::thread> threads;
|
||||||
|
|
||||||
void printUsage();
|
void printUsage();
|
||||||
inline bool isInteger(const std::string & s);
|
inline bool isInteger(const std::string & s);
|
||||||
bool ichar_equals(char a, char b);
|
bool ichar_equals(char a, char b);
|
||||||
@ -166,8 +169,7 @@ int main (int argc, char* argv[])
|
|||||||
inet_ntoa(cliaddress.sin_addr),
|
inet_ntoa(cliaddress.sin_addr),
|
||||||
ntohs(cliaddress.sin_port));
|
ntohs(cliaddress.sin_port));
|
||||||
// clientCommunication(&new_socket); // returnValue can be ignored
|
// clientCommunication(&new_socket); // returnValue can be ignored
|
||||||
std::thread th(clientCommunication, new_socket);
|
threads.emplace_back(clientCommunication, new_socket);
|
||||||
th.detach();
|
|
||||||
new_socket = -1;
|
new_socket = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -305,7 +307,7 @@ void signalHandler(int sig)
|
|||||||
{
|
{
|
||||||
if (sig == SIGINT) {
|
if (sig == SIGINT) {
|
||||||
printf("abort Requested... "); // ignore error
|
printf("abort Requested... "); // ignore error
|
||||||
abortRequested = 1;
|
abortRequested = true;
|
||||||
if (new_socket != -1)
|
if (new_socket != -1)
|
||||||
{
|
{
|
||||||
if (shutdown(new_socket, SHUT_RDWR) == -1)
|
if (shutdown(new_socket, SHUT_RDWR) == -1)
|
||||||
@ -363,6 +365,10 @@ std::string getSha1(const std::string& str)
|
|||||||
|
|
||||||
inline void exiting()
|
inline void exiting()
|
||||||
{
|
{
|
||||||
|
for (auto& thread : threads) {
|
||||||
|
thread.join();
|
||||||
|
}
|
||||||
|
|
||||||
user_handler::getInstance().saveAll();
|
user_handler::getInstance().saveAll();
|
||||||
printf("Saving... \n");
|
printf("Saving... \n");
|
||||||
}
|
}
|
||||||
@ -420,13 +426,14 @@ std::string cmdREAD(std::vector<std::string>& received)
|
|||||||
mail->deleted)
|
mail->deleted)
|
||||||
return "ERR\n";
|
return "ERR\n";
|
||||||
|
|
||||||
try {
|
/*try */{
|
||||||
std::string path_str = user_handler::getInstance().getSpoolDir()/"messages"/mail->filename;
|
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");
|
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 "ERR\n";
|
||||||
}
|
}*/
|
||||||
|
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
#include <cstdio>
|
#include <cstdio>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <mutex>
|
||||||
#include <ostream>
|
#include <ostream>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -11,7 +12,7 @@
|
|||||||
|
|
||||||
using json = nlohmann::json;
|
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);
|
std::ifstream ifs(user_data_json);
|
||||||
json user_data = json::parse(ifs);
|
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)
|
user::user(std::string name, fs::path user_dir)
|
||||||
: name(name)
|
: name(name),
|
||||||
|
m()
|
||||||
{
|
{
|
||||||
json user;
|
json user;
|
||||||
user["mails"]["sent"] = json::object();
|
user["mails"]["sent"] = json::object();
|
||||||
@ -69,6 +71,8 @@ user::~user() {
|
|||||||
|
|
||||||
void user::addMail(mail* mail)
|
void user::addMail(mail* mail)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(this->m);
|
||||||
|
|
||||||
mail->id = this->inbox.size();
|
mail->id = this->inbox.size();
|
||||||
|
|
||||||
this->inbox.insert(mail);
|
this->inbox.insert(mail);
|
||||||
@ -77,6 +81,8 @@ void user::addMail(mail* mail)
|
|||||||
|
|
||||||
void user::sendMail(mail* mail, std::vector<std::string> recipients)
|
void user::sendMail(mail* mail, std::vector<std::string> recipients)
|
||||||
{
|
{
|
||||||
|
std::lock_guard<std::mutex> guard(this->m);
|
||||||
|
|
||||||
std::vector<user*> users;
|
std::vector<user*> users;
|
||||||
for ( auto& name : recipients) {
|
for ( auto& name : recipients) {
|
||||||
// TODO: error handling for non existing user
|
// TODO: error handling for non existing user
|
||||||
@ -104,6 +110,8 @@ mail* user::getMail(u_int id)
|
|||||||
|
|
||||||
bool user::delMail(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); });
|
maillist::iterator it = std::find_if(this->inbox.begin(), this->inbox.end(), [id](auto& i){ return (*i)(id); });
|
||||||
|
|
||||||
bool success = true;
|
bool success = true;
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include "mail.h"
|
#include "mail.h"
|
||||||
|
|
||||||
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <set>
|
#include <set>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
@ -37,4 +38,6 @@ private:
|
|||||||
std::string name;
|
std::string name;
|
||||||
maillist inbox;
|
maillist inbox;
|
||||||
maillist sent;
|
maillist sent;
|
||||||
|
|
||||||
|
std::mutex m;
|
||||||
};
|
};
|
||||||
@ -4,7 +4,7 @@
|
|||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
user_handler::user_handler()
|
user_handler::user_handler() : m_user()
|
||||||
{
|
{
|
||||||
for (const auto& entry : fs::directory_iterator()) {
|
for (const auto& entry : fs::directory_iterator()) {
|
||||||
if (entry.path().extension() == ".json") {
|
if (entry.path().extension() == ".json") {
|
||||||
@ -21,26 +21,31 @@ user_handler::~user_handler()
|
|||||||
user* user_handler::getUser(std::string name)
|
user* user_handler::getUser(std::string name)
|
||||||
{
|
{
|
||||||
if (this->users.find(name) == this->users.end()) {
|
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")))
|
if (!fs::exists(this->spool_dir/"users"/(name+".json")))
|
||||||
return nullptr;
|
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)
|
user* user_handler::getOrCreateUser(std::string name)
|
||||||
{
|
{
|
||||||
if (this->users.find(name) == this->users.end()) {
|
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(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];
|
return this->users[name];
|
||||||
}
|
}
|
||||||
|
|
||||||
void user_handler::saveAll()
|
void user_handler::saveAll()
|
||||||
{
|
{
|
||||||
|
// will only be called from main
|
||||||
for ( auto& user : this->users ) {
|
for ( auto& user : this->users ) {
|
||||||
user.second->saveToFile();
|
user.second->saveToFile();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
class user;
|
class user;
|
||||||
@ -38,4 +39,6 @@ protected:
|
|||||||
fs::path spool_dir;
|
fs::path spool_dir;
|
||||||
std::map<std::string, user*> users;
|
std::map<std::string, user*> users;
|
||||||
|
|
||||||
|
std::mutex m_user;
|
||||||
|
|
||||||
};
|
};
|
||||||
Loading…
x
Reference in New Issue
Block a user