mirror of
https://github.com/sigmasternchen/CFloor
synced 2025-03-15 20:28:56 +00:00
restructured signal management to avoid multible threads in the same critical section
This commit is contained in:
parent
0dcb33fe68
commit
b39fb7bcd8
4 changed files with 40 additions and 17 deletions
|
@ -7,6 +7,10 @@
|
||||||
#include <assert.h>
|
#include <assert.h>
|
||||||
#include <semaphore.h>
|
#include <semaphore.h>
|
||||||
|
|
||||||
|
#ifdef DEBUG
|
||||||
|
#include <pthread.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
|
@ -186,6 +190,9 @@ void vlogging(loglevel_t loglevel, const char* format, va_list argptr) {
|
||||||
sem_wait(&(logger[i].write_sem));
|
sem_wait(&(logger[i].write_sem));
|
||||||
|
|
||||||
fprintf(logger[i].file, "%s %s ", timestamp, loglevelString);
|
fprintf(logger[i].file, "%s %s ", timestamp, loglevelString);
|
||||||
|
#ifdef DEBUG
|
||||||
|
fprintf(logger[i].file, "[%ld] ", pthread_self());
|
||||||
|
#endif
|
||||||
vfprintf(logger[i].file, format, local);
|
vfprintf(logger[i].file, format, local);
|
||||||
fprintf(logger[i].file, "\n");
|
fprintf(logger[i].file, "\n");
|
||||||
|
|
||||||
|
|
|
@ -54,8 +54,6 @@ linkedList_t connectionList;
|
||||||
|
|
||||||
linkedList_t connectionsToFree;
|
linkedList_t connectionsToFree;
|
||||||
void cleanup() {
|
void cleanup() {
|
||||||
signal_block_all();
|
|
||||||
|
|
||||||
link_t* link = linked_first(&connectionList);
|
link_t* link = linked_first(&connectionList);
|
||||||
|
|
||||||
int length = 0;
|
int length = 0;
|
||||||
|
@ -629,8 +627,6 @@ void* responseThread(void* data) {
|
||||||
void* requestThread(void* data) {
|
void* requestThread(void* data) {
|
||||||
struct connection* connection = (struct connection*) data;
|
struct connection* connection = (struct connection*) data;
|
||||||
|
|
||||||
signal_block_all();
|
|
||||||
|
|
||||||
struct handler handler = networkingConfig.getHandler(connection->metaData, headers_get(&(connection->headers), "Host"), connection->bind);
|
struct handler handler = networkingConfig.getHandler(connection->metaData, headers_get(&(connection->headers), "Host"), connection->bind);
|
||||||
|
|
||||||
if (handler.handler == NULL) {
|
if (handler.handler == NULL) {
|
||||||
|
@ -692,7 +688,7 @@ void startRequestHandler(struct connection* connection) {
|
||||||
|
|
||||||
pthread_t dataThreadId;
|
pthread_t dataThreadId;
|
||||||
|
|
||||||
void dataHandler(int signo) {
|
void dataHandler() {
|
||||||
pthread_t self = pthread_self();
|
pthread_t self = pthread_self();
|
||||||
|
|
||||||
debug("networking: data handler got called.");
|
debug("networking: data handler got called.");
|
||||||
|
@ -868,6 +864,7 @@ void dataHandler(int signo) {
|
||||||
// if the connection ends (tmp == 0)
|
// if the connection ends (tmp == 0)
|
||||||
// the connection has to be dropped to free resources before the timeout
|
// the connection has to be dropped to free resources before the timeout
|
||||||
if (dropConnection) {
|
if (dropConnection) {
|
||||||
|
connection->currentHeaderLength = 0;
|
||||||
if (connection->currentHeader != NULL)
|
if (connection->currentHeader != NULL)
|
||||||
free(connection->currentHeader);
|
free(connection->currentHeader);
|
||||||
connection->currentHeader = NULL;
|
connection->currentHeader = NULL;
|
||||||
|
@ -886,19 +883,17 @@ void dataHandler(int signo) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void* dataThread(void* ignore) {
|
void* dataThread(void* ignore) {
|
||||||
signal_block_all();
|
|
||||||
signal_allow(SIGIO);
|
|
||||||
|
|
||||||
signal_setup(SIGIO, &dataHandler);
|
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
sleep(0xffff);
|
if (signal_wait(SIGIO) != 0) {
|
||||||
|
error("networking: data thread: sigwait: %s", strerror(errno));
|
||||||
|
debug("networking: data thread: waiting 1s");
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
dataHandler();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void* listenThread(void* _bind) {
|
void* listenThread(void* _bind) {
|
||||||
signal_block_all();
|
|
||||||
|
|
||||||
struct bind* bindObj = (struct bind*) _bind;
|
struct bind* bindObj = (struct bind*) _bind;
|
||||||
|
|
||||||
info("networking: Starting to listen on %s:%s", bindObj->address, bindObj->port);
|
info("networking: Starting to listen on %s:%s", bindObj->address, bindObj->port);
|
||||||
|
@ -1127,13 +1122,27 @@ void* listenThread(void* _bind) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void cleanupThread() {
|
||||||
|
while(true) {
|
||||||
|
if (signal_wait(SIGALRM) != 0) {
|
||||||
|
error("networking: clean up thread: sigwait: %s", strerror(errno));
|
||||||
|
debug("networking: clean up thread: waiting 1s");
|
||||||
|
sleep(1);
|
||||||
|
}
|
||||||
|
cleanup();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void networking_init(struct networkingConfig _networkingConfig) {
|
void networking_init(struct networkingConfig _networkingConfig) {
|
||||||
networkingConfig = _networkingConfig;
|
networkingConfig = _networkingConfig;
|
||||||
|
|
||||||
connectionList = linked_create();
|
connectionList = linked_create();
|
||||||
connectionsToFree = linked_create();
|
connectionsToFree = linked_create();
|
||||||
|
|
||||||
timer_t timer = timer_createThreadTimer(&cleanup);
|
signal_block(SIGIO);
|
||||||
|
signal_block(SIGALRM);
|
||||||
|
|
||||||
|
timer_t timer = timer_createSignalTimer(SIGALRM);
|
||||||
if (timer == NULL) {
|
if (timer == NULL) {
|
||||||
critical("networking: Couldn't create cleaup timer.");
|
critical("networking: Couldn't create cleaup timer.");
|
||||||
return;
|
return;
|
||||||
|
@ -1148,9 +1157,6 @@ void networking_init(struct networkingConfig _networkingConfig) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
signal_block(SIGIO);
|
|
||||||
signal_block(SIGALRM);
|
|
||||||
|
|
||||||
for(int i = 0; i < networkingConfig.binds.number; i++) {
|
for(int i = 0; i < networkingConfig.binds.number; i++) {
|
||||||
struct bind* bind = &(networkingConfig.binds.binds[i]);
|
struct bind* bind = &(networkingConfig.binds.binds[i]);
|
||||||
if (pthread_create(&(bind->_private.threadId), NULL, &listenThread, bind) != 0) {
|
if (pthread_create(&(bind->_private.threadId), NULL, &listenThread, bind) != 0) {
|
||||||
|
|
|
@ -39,6 +39,15 @@ int signal_allow(int signo) {
|
||||||
return pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
|
return pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int signal_wait(int signo) {
|
||||||
|
sigset_t mask;
|
||||||
|
sigemptyset(&mask);
|
||||||
|
sigaddset(&mask, signo);
|
||||||
|
|
||||||
|
int _;
|
||||||
|
return sigwait(&mask, &_);
|
||||||
|
}
|
||||||
|
|
||||||
static void timerHandler(union sigval target) {
|
static void timerHandler(union sigval target) {
|
||||||
((void (*)(void))(target.sival_ptr))();
|
((void (*)(void))(target.sival_ptr))();
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,6 +8,7 @@ int signal_block_all();
|
||||||
int signal_allow_all();
|
int signal_allow_all();
|
||||||
int signal_block(int signo);
|
int signal_block(int signo);
|
||||||
int signal_allow(int signo);
|
int signal_allow(int signo);
|
||||||
|
int signal_wait(int signo);
|
||||||
|
|
||||||
timer_t timer_createThreadTimer(void (*handler)());
|
timer_t timer_createThreadTimer(void (*handler)());
|
||||||
timer_t timer_createSignalTimer(int signo);
|
timer_t timer_createSignalTimer(int signo);
|
||||||
|
|
Loading…
Reference in a new issue