#include "dolog.hh"
#include "dnscrypt.hh"
#include "dnswriter.hh"
-#include "lock.hh"
DNSCryptPrivateKey::DNSCryptPrivateKey()
{
DNSCryptContext::~DNSCryptContext() {
- pthread_rwlock_destroy(&d_lock);
}
DNSCryptContext::DNSCryptContext(const std::string& pName, const std::vector<CertKeyPaths>& certKeys): d_certKeyPaths(certKeys), providerName(pName)
{
- pthread_rwlock_init(&d_lock, 0);
-
reloadCertificates();
}
DNSCryptContext::DNSCryptContext(const std::string& pName, const DNSCryptCert& certificate, const DNSCryptPrivateKey& pKey): providerName(pName)
{
- pthread_rwlock_init(&d_lock, 0);
-
addNewCertificate(certificate, pKey);
}
#include <sodium.h>
#include "dnsname.hh"
+#include "lock.hh"
#define DNSCRYPT_PROVIDER_PUBLIC_KEY_SIZE (crypto_sign_ed25519_PUBLICKEYBYTES)
#define DNSCRYPT_PROVIDER_PRIVATE_KEY_SIZE (crypto_sign_ed25519_SECRETKEYBYTES)
void addNewCertificate(std::shared_ptr<DNSCryptCertificatePair>& newCert, bool reload=false);
- pthread_rwlock_t d_lock;
+ ReadWriteLock d_lock;
std::vector<std::shared_ptr<DNSCryptCertificatePair>> d_certs;
std::vector<CertKeyPaths> d_certKeyPaths;
DNSName providerName;
public:
CacheShard(): d_entriesCount(0)
{
- pthread_rwlock_init(&d_lock, nullptr);
}
CacheShard(const CacheShard& old): d_entriesCount(0)
{
- pthread_rwlock_init(&d_lock, nullptr);
- }
- ~CacheShard() {
- pthread_rwlock_destroy(&d_lock);
}
+
void setSize(size_t maxSize)
{
d_map.reserve(maxSize);
}
std::unordered_map<uint32_t,CacheValue> d_map;
- pthread_rwlock_t d_lock;
+ ReadWriteLock d_lock;
std::atomic<uint64_t> d_entriesCount;
};
struct QueryCount {
QueryCount()
{
- pthread_rwlock_init(&queryLock, nullptr);
}
~QueryCount()
{
- pthread_rwlock_destroy(&queryLock);
}
QueryCountRecords records;
QueryCountFilter filter;
- pthread_rwlock_t queryLock;
+ ReadWriteLock queryLock;
bool enabled{false};
};
fd = -1;
}
}
- pthread_rwlock_destroy(&d_lock);
}
boost::uuids::uuid id;
std::vector<unsigned int> hashes;
- mutable pthread_rwlock_t d_lock;
+ mutable ReadWriteLock d_lock;
std::vector<int> sockets;
const std::string sourceItfName;
std::mutex socketsLock;
{
ServerPool()
{
- pthread_rwlock_init(&d_lock, nullptr);
}
~ServerPool()
{
- pthread_rwlock_destroy(&d_lock);
}
const std::shared_ptr<DNSDistPacketCache> getCache() const { return packetCache; };
private:
ServerPolicy::NumberedServerVector d_servers;
- pthread_rwlock_t d_lock;
+ ReadWriteLock d_lock;
bool d_useECS{false};
};
DownstreamState::DownstreamState(const ComboAddress& remote_, const ComboAddress& sourceAddr_, unsigned int sourceItf_, const std::string& sourceItfName_, size_t numberOfSockets, bool connect=true): sourceItfName(sourceItfName_), remote(remote_), sourceAddr(sourceAddr_), sourceItf(sourceItf_), name(remote_.toStringWithPort()), nameWithAddr(remote_.toStringWithPort())
{
- pthread_rwlock_init(&d_lock, nullptr);
id = getUniqueID();
threadStarted.clear();
CDBKVStore::CDBKVStore(const std::string& fname, time_t refreshDelay): d_fname(fname), d_refreshDelay(refreshDelay)
{
- pthread_rwlock_init(&d_lock, nullptr);
d_refreshing.clear();
time_t now = time(nullptr);
}
CDBKVStore::~CDBKVStore() {
- pthread_rwlock_destroy(&d_lock);
}
bool CDBKVStore::reload(const struct stat& st)
std::unique_ptr<CDB> d_cdb{nullptr};
std::string d_fname;
- pthread_rwlock_t d_lock;
+ ReadWriteLock d_lock;
time_t d_mtime{0};
time_t d_nextCheck{0};
time_t d_refreshDelay{0};
public:
TimedIPSetRule()
{
- pthread_rwlock_init(&d_lock4, 0);
- pthread_rwlock_init(&d_lock6, 0);
}
~TimedIPSetRule()
{
- pthread_rwlock_destroy(&d_lock4);
- pthread_rwlock_destroy(&d_lock6);
}
bool matches(const DNSQuestion* dq) const override
{
void cleanup()
{
- time_t now=time(0);
+ time_t now = time(nullptr);
{
WriteLock rl(&d_lock4);
};
std::unordered_map<IPv6, time_t, IPv6Hash> d_ip6s;
std::unordered_map<uint32_t, time_t> d_ip4s;
- mutable pthread_rwlock_t d_lock4;
- mutable pthread_rwlock_t d_lock6;
+ mutable ReadWriteLock d_lock4;
+ mutable ReadWriteLock d_lock6;
};
#include <atomic>
#include <fstream>
#include <cstring>
+#include <mutex>
#include <pthread.h>
#include <openssl/conf.h>
#if (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2090100fL)
/* OpenSSL < 1.1.0 needs support for threading/locking in the calling application. */
-static pthread_mutex_t *openssllocks{nullptr};
+
+#include "lock.hh"
+static std::vector<std::mutex> openssllocks;
extern "C" {
static void openssl_pthreads_locking_callback(int mode, int type, const char *file, int line)
{
if (mode & CRYPTO_LOCK) {
- pthread_mutex_lock(&(openssllocks[type]));
+ openssllocks.at(type).lock();
} else {
- pthread_mutex_unlock(&(openssllocks[type]));
+ openssllocks.at(type).unlock();
}
}
static void openssl_thread_setup()
{
- openssllocks = (pthread_mutex_t*)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
-
- for (int i = 0; i < CRYPTO_num_locks(); i++)
- pthread_mutex_init(&(openssllocks[i]), NULL);
-
- CRYPTO_set_id_callback(openssl_pthreads_id_callback);
- CRYPTO_set_locking_callback(openssl_pthreads_locking_callback);
+ openssllocks = std::vector<std::mutex>(CRYPTO_num_locks());
+ CRYPTO_set_id_callback(&openssl_pthreads_id_callback);
+ CRYPTO_set_locking_callback(&openssl_pthreads_locking_callback);
}
static void openssl_thread_cleanup()
{
- CRYPTO_set_locking_callback(NULL);
-
- for (int i=0; i<CRYPTO_num_locks(); i++) {
- pthread_mutex_destroy(&(openssllocks[i]));
- }
-
- OPENSSL_free(openssllocks);
+ CRYPTO_set_locking_callback(nullptr);
+ openssllocks.clear();
}
#endif /* (OPENSSL_VERSION_NUMBER < 0x1010000fL || (defined LIBRESSL_VERSION_NUMBER) && LIBRESSL_VERSION_NUMBER < 0x2090100fL) */
OpenSSLTLSTicketKeysRing::OpenSSLTLSTicketKeysRing(size_t capacity)
{
- pthread_rwlock_init(&d_lock, nullptr);
d_ticketKeys.set_capacity(capacity);
}
OpenSSLTLSTicketKeysRing::~OpenSSLTLSTicketKeysRing()
{
- pthread_rwlock_destroy(&d_lock);
}
void OpenSSLTLSTicketKeysRing::addKey(std::shared_ptr<OpenSSLTLSTicketKey> newKey)
throw std::runtime_error("Error setting up TLS cipher preferences to '" + fe.d_tlsConfig.d_ciphers + "' (" + gnutls_strerror(rc) + ") on " + fe.d_addr.toStringWithPort());
}
- pthread_rwlock_init(&d_lock, nullptr);
-
try {
if (fe.d_tlsConfig.d_ticketKeyFile.empty()) {
handleTicketsKeyRotation(time(nullptr));
}
}
catch(const std::runtime_error& e) {
- pthread_rwlock_destroy(&d_lock);
throw std::runtime_error("Error generating tickets key for TLS context on " + fe.d_addr.toStringWithPort() + ": " + e.what());
}
}
virtual ~GnuTLSIOCtx() override
{
- pthread_rwlock_destroy(&d_lock);
-
d_creds.reset();
if (d_priorityCache) {
std::unique_ptr<gnutls_certificate_credentials_st, void(*)(gnutls_certificate_credentials_t)> d_creds;
gnutls_priority_t d_priorityCache{nullptr};
std::shared_ptr<GnuTLSTicketsKey> d_ticketsKey{nullptr};
- pthread_rwlock_t d_lock;
+ ReadWriteLock d_lock;
bool d_enableTickets{true};
};
private:
boost::circular_buffer<std::shared_ptr<OpenSSLTLSTicketKey> > d_ticketKeys;
- pthread_rwlock_t d_lock;
+ ReadWriteLock d_lock;
};
void* libssl_get_ticket_key_callback_data(SSL* s);
}
};
+class ReadWriteLock
+{
+public:
+ ReadWriteLock()
+ {
+ if (pthread_rwlock_init(&d_lock, nullptr) != 0) {
+ throw std::runtime_error("Error creating a read-write lock: " + stringerror());
+ }
+ }
+
+ ~ReadWriteLock() {
+ /* might have been moved */
+ pthread_rwlock_destroy(&d_lock);
+ }
+
+ ReadWriteLock(const ReadWriteLock& rhs) = delete;
+ ReadWriteLock& operator=(const ReadWriteLock& rhs) = delete;
+
+ pthread_rwlock_t* getLock()
+ {
+ return &d_lock;
+ }
+
+private:
+ pthread_rwlock_t d_lock;
+};
+
class WriteLock
{
pthread_rwlock_t *d_lock;
pthread_rwlock_unlock(d_lock);
}
+ WriteLock(ReadWriteLock& lock): WriteLock(lock.getLock())
+ {
+ }
+
+ WriteLock(ReadWriteLock* lock): WriteLock(lock->getLock())
+ {
+ }
+
WriteLock(WriteLock&& rhs)
{
d_lock = rhs.d_lock;
rhs.d_havelock = false;
}
-
+ TryWriteLock(ReadWriteLock& lock): TryWriteLock(lock.getLock())
+ {
+ }
+
+ TryWriteLock(ReadWriteLock* lock): TryWriteLock(lock->getLock())
+ {
+ }
+
~TryWriteLock()
{
if(g_singleThreaded)
}
d_havelock=(err==0);
}
+
+ TryReadLock(ReadWriteLock& lock): TryReadLock(lock.getLock())
+ {
+ }
+
+ TryReadLock(ReadWriteLock* lock): TryReadLock(lock->getLock())
+ {
+ }
+
TryReadLock(TryReadLock&& rhs)
{
d_lock = rhs.d_lock;
throw PDNSException("error acquiring rwlock readlock: "+stringerror(err));
}
}
+
+ ReadLock(ReadWriteLock& lock): ReadLock(lock.getLock())
+ {
+ }
+
+ ReadLock(ReadWriteLock* lock): ReadLock(lock->getLock())
+ {
+ }
+
~ReadLock()
{
if(g_singleThreaded)
ReadLock(ReadLock&& rhs)
{
d_lock = rhs.d_lock;
- rhs.d_lock=0;
+ rhs.d_lock = nullptr;
}
ReadLock(const ReadLock& rhs) = delete;
ReadLock& operator=(const ReadLock& rhs) = delete;
static DNSDistPacketCache g_PC(500000);
-static void *threadMangler(void* off)
+static void threadMangler(unsigned int offset)
{
struct timespec queryTime;
gettime(&queryTime); // does not have to be accurate ("realTime") in tests
try {
ComboAddress remote;
bool dnssecOK = false;
- unsigned int offset=(unsigned int)(unsigned long)off;
for(unsigned int counter=0; counter < 100000; ++counter) {
DNSName a=DNSName("hello ")+DNSName(std::to_string(counter+offset));
vector<uint8_t> query;
cerr<<"Had error: "<<e.reason<<endl;
throw;
}
- return 0;
}
AtomicCounter g_missing;
-static void *threadReader(void* off)
+static void threadReader(unsigned int offset)
{
bool dnssecOK = false;
struct timespec queryTime;
gettime(&queryTime); // does not have to be accurate ("realTime") in tests
try
{
- unsigned int offset=(unsigned int)(unsigned long)off;
vector<DNSResourceRecord> entry;
ComboAddress remote;
for(unsigned int counter=0; counter < 100000; ++counter) {
cerr<<"Had error in threadReader: "<<e.reason<<endl;
throw;
}
- return 0;
}
BOOST_AUTO_TEST_CASE(test_PacketCacheThreaded) {
try {
- pthread_t tid[4];
- for(int i=0; i < 4; ++i)
- pthread_create(&tid[i], 0, threadMangler, (void*)(i*1000000UL));
- void* res;
- for(int i=0; i < 4 ; ++i)
- pthread_join(tid[i], &res);
+ std::vector<std::thread> threads;
+ for (int i = 0; i < 4; ++i) {
+ threads.push_back(std::thread(threadMangler, i*1000000UL));
+ }
+
+ for (auto& t : threads) {
+ t.join();
+ }
+
+ threads.clear();
BOOST_CHECK_EQUAL(g_PC.getSize() + g_PC.getDeferredInserts() + g_PC.getInsertCollisions(), 400000U);
BOOST_CHECK_SMALL(1.0*g_PC.getInsertCollisions(), 10000.0);
- for(int i=0; i < 4; ++i)
- pthread_create(&tid[i], 0, threadReader, (void*)(i*1000000UL));
- for(int i=0; i < 4 ; ++i)
- pthread_join(tid[i], &res);
+ for (int i = 0; i < 4; ++i) {
+ threads.push_back(std::thread(threadReader, i*1000000UL));
+ }
+
+ for (auto& t : threads) {
+ t.join();
+ }
BOOST_CHECK((g_PC.getDeferredInserts() + g_PC.getDeferredLookups() + g_PC.getInsertCollisions()) >= g_missing);
}