mirror of
https://github.com/sigmasternchen/CFloor
synced 2025-03-15 20:28:56 +00:00
signals + tests
This commit is contained in:
parent
4b6cbba04f
commit
fa9cc3b8cc
4 changed files with 212 additions and 20 deletions
7
Makefile
7
Makefile
|
@ -1,5 +1,5 @@
|
||||||
CC = gcc
|
CC = gcc
|
||||||
CFLAGS = -Wall -Wpedantic
|
CFLAGS = -std=c99 -Wall -D_POSIX_C_SOURCE=199506L
|
||||||
LD = gcc
|
LD = gcc
|
||||||
LDFLAGS = -lpthread -lrt
|
LDFLAGS = -lpthread -lrt
|
||||||
|
|
||||||
|
@ -7,16 +7,17 @@ BIN_NAME = cfloor
|
||||||
|
|
||||||
all: $(BIN_NAME)
|
all: $(BIN_NAME)
|
||||||
|
|
||||||
test: obj/test.o obj/networking.o obj/linked.o obj/logging.o
|
test: obj/test.o obj/networking.o obj/linked.o obj/logging.o obj/signals.o
|
||||||
$(LD) $(LDFLAGS) -o $@ $^
|
$(LD) $(LDFLAGS) -o $@ $^
|
||||||
valgrind: CFLAGS += -static -g
|
valgrind: CFLAGS += -static -g
|
||||||
valgrind: clean test
|
valgrind: clean test
|
||||||
valgrind --leak-check=yes ./test
|
valgrind --leak-check=yes ./test
|
||||||
|
|
||||||
obj/test.o: src/networking.h src/linked.h src/logging.h
|
obj/test.o: src/networking.h src/linked.h src/logging.h src/signals.h
|
||||||
obj/networking.o: src/networking.h src/headers.h src/linked.h
|
obj/networking.o: src/networking.h src/headers.h src/linked.h
|
||||||
obj/linked.o: src/linked.h
|
obj/linked.o: src/linked.h
|
||||||
obj/loggin.o: src/logging.h
|
obj/loggin.o: src/logging.h
|
||||||
|
obj/signals.o: src/signals.h
|
||||||
|
|
||||||
obj/%.o: src/%.c obj
|
obj/%.o: src/%.c obj
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
102
src/signals.c
Normal file
102
src/signals.c
Normal file
|
@ -0,0 +1,102 @@
|
||||||
|
#include <signal.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
#include <time.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "signals.h"
|
||||||
|
|
||||||
|
int signal_setup(int signo, void (*handler)(int signo)) {
|
||||||
|
struct sigaction action;
|
||||||
|
|
||||||
|
action.sa_flags = 0;
|
||||||
|
action.sa_handler = handler;
|
||||||
|
|
||||||
|
return sigaction(signo, &action, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int signal_block_all() {
|
||||||
|
sigset_t mask;
|
||||||
|
sigfillset(&mask);
|
||||||
|
return pthread_sigmask(SIG_BLOCK, &mask, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
int signal_allow_all() {
|
||||||
|
sigset_t mask;
|
||||||
|
sigfillset(&mask);
|
||||||
|
return pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
|
||||||
|
}
|
||||||
|
int signal_block(int signo) {
|
||||||
|
sigset_t mask;
|
||||||
|
sigaddset(&mask, signo);
|
||||||
|
return pthread_sigmask(SIG_BLOCK, &mask, NULL);
|
||||||
|
}
|
||||||
|
int signal_allow(int signo) {
|
||||||
|
sigset_t mask;
|
||||||
|
sigaddset(&mask, signo);
|
||||||
|
return pthread_sigmask(SIG_UNBLOCK, &mask, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void timerHandler(union sigval target) {
|
||||||
|
((void (*)(void))(target.sival_ptr))();
|
||||||
|
}
|
||||||
|
timer_t timer_createThreadTimer(void (*handler)()) {
|
||||||
|
struct sigevent sevp;
|
||||||
|
sevp.sigev_notify = SIGEV_THREAD;
|
||||||
|
sevp.sigev_notify_function = timerHandler;
|
||||||
|
sevp.sigev_notify_attributes = NULL;
|
||||||
|
sevp.sigev_value.sival_ptr = (void*) handler;
|
||||||
|
|
||||||
|
timer_t timer;
|
||||||
|
|
||||||
|
if (timer_create(CLOCK_BOOTTIME, &sevp, &timer) < 0) {
|
||||||
|
timer = NULL;
|
||||||
|
}
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
timer_t timer_createSignalTimer(int signo) {
|
||||||
|
struct sigevent sevp;
|
||||||
|
sevp.sigev_notify = SIGEV_SIGNAL;
|
||||||
|
sevp.sigev_signo = signo;
|
||||||
|
|
||||||
|
timer_t timer;
|
||||||
|
|
||||||
|
if (timer_create(CLOCK_BOOTTIME, &sevp, &timer) < 0) {
|
||||||
|
timer = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timer;
|
||||||
|
}
|
||||||
|
int timer_destroy(timer_t timer) {
|
||||||
|
return timer_delete(timer);
|
||||||
|
}
|
||||||
|
|
||||||
|
int timer_startTimer(timer_t timer, unsigned long ms) {
|
||||||
|
struct itimerspec time, old;
|
||||||
|
|
||||||
|
time.it_value.tv_sec = ms / 1000;
|
||||||
|
time.it_value.tv_nsec = ((ms % 1000) * 1000000);
|
||||||
|
time.it_interval.tv_sec = 0;
|
||||||
|
time.it_interval.tv_nsec = 0;
|
||||||
|
|
||||||
|
return timer_settime(timer, 0, &time, &old);
|
||||||
|
}
|
||||||
|
int timer_startInterval(timer_t timer, unsigned long ms) {
|
||||||
|
struct itimerspec time, old;
|
||||||
|
|
||||||
|
time.it_value.tv_sec = ms / 1000;
|
||||||
|
time.it_value.tv_nsec = ((ms % 1000) * 1000000);
|
||||||
|
time.it_interval.tv_sec = ms / 1000;
|
||||||
|
time.it_interval.tv_nsec = ((ms % 1000) * 1000000);
|
||||||
|
|
||||||
|
return timer_settime(timer, 0, &time, &old);
|
||||||
|
}
|
||||||
|
int timer_stop(timer_t timer) {
|
||||||
|
struct itimerspec time, old;
|
||||||
|
|
||||||
|
time.it_value.tv_sec = 0;
|
||||||
|
time.it_value.tv_nsec = 0;
|
||||||
|
time.it_interval.tv_sec = 0;
|
||||||
|
time.it_interval.tv_nsec = 0;
|
||||||
|
|
||||||
|
return timer_settime(timer, 0, &time, &old);
|
||||||
|
}
|
20
src/signals.h
Normal file
20
src/signals.h
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef SIGNALS_H
|
||||||
|
#define SIGNALS_H
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
|
int signal_setup(int signum, void (*handler)(int signo));
|
||||||
|
int signal_block_all();
|
||||||
|
int signal_allow_all();
|
||||||
|
int signal_block(int signo);
|
||||||
|
int signal_allow(int signo);
|
||||||
|
|
||||||
|
timer_t timer_createThreadTimer(void (*handler)());
|
||||||
|
timer_t timer_createSignalTimer(int signo);
|
||||||
|
int timer_destroy(timer_t timer);
|
||||||
|
|
||||||
|
int timer_startTimer(timer_t timer, unsigned long ms);
|
||||||
|
int timer_startInterval(timer_t timer, unsigned long ms);
|
||||||
|
int timer_stop(timer_t timer);
|
||||||
|
|
||||||
|
#endif
|
103
src/test.c
103
src/test.c
|
@ -2,12 +2,20 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/select.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <poll.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include "networking.h"
|
#include "networking.h"
|
||||||
#include "linked.h"
|
#include "linked.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
|
#include "signals.h"
|
||||||
|
|
||||||
bool global = true;
|
bool global = true;
|
||||||
|
bool overall = true;
|
||||||
|
|
||||||
void checkBool(bool ok, const char* check) {
|
void checkBool(bool ok, const char* check) {
|
||||||
const char* result;
|
const char* result;
|
||||||
|
@ -33,6 +41,10 @@ void checkNull(void* value, const char* check) {
|
||||||
checkBool(value != NULL, check);
|
checkBool(value != NULL, check);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void showError() {
|
||||||
|
fprintf(stderr, "Error: %s\n", strerror(errno));
|
||||||
|
}
|
||||||
|
|
||||||
void testLinkedList() {
|
void testLinkedList() {
|
||||||
linkedList_t list = linked_create();
|
linkedList_t list = linked_create();
|
||||||
|
|
||||||
|
@ -85,20 +97,80 @@ void testLinkedList() {
|
||||||
linked_destroy(&list);
|
linked_destroy(&list);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool hasData(int fd) {
|
||||||
|
int tmp = poll(&(struct pollfd){ .fd = fd, .events = POLLIN }, 1, 10);
|
||||||
|
|
||||||
|
return tmp == 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool handlerHasTriggered = false;
|
||||||
void criticalHandler() {
|
void criticalHandler() {
|
||||||
printf("This is the critical handler.\n");
|
printf("This is the critical handler.\n");
|
||||||
printBacktrace();
|
printBacktrace();
|
||||||
}
|
}
|
||||||
void testLogging() {
|
void testLogging() {
|
||||||
|
int pipefd[2];
|
||||||
|
if (pipe(pipefd) < 0) {
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
FILE* pipeWrite = fdopen(pipefd[1], "w");
|
||||||
|
if (pipeWrite == NULL) {
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setbuf(pipeWrite, NULL);
|
||||||
|
FILE* pipeRead = fdopen(pipefd[0], "r");
|
||||||
|
if (pipeRead == NULL) {
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
setbuf(pipeRead, NULL);
|
||||||
|
|
||||||
|
setLogging(pipeWrite, DEFAULT_LOGLEVEL, false);
|
||||||
setLogging(stderr, DEFAULT_LOGLEVEL, true);
|
setLogging(stderr, DEFAULT_LOGLEVEL, true);
|
||||||
|
|
||||||
info("This info should not be displayed.");
|
info("This info should not be displayed.");
|
||||||
|
checkBool(!hasData(pipefd[0]), "no data read (info)");
|
||||||
|
|
||||||
warn("This warning should be displayed.");
|
warn("This warning should be displayed.");
|
||||||
|
checkBool(hasData(pipefd[0]), "data read (warn)");
|
||||||
|
fflush(pipeRead);
|
||||||
|
|
||||||
error("This error should be displayed.");
|
error("This error should be displayed.");
|
||||||
|
checkBool(hasData(pipefd[0]), "data read (error)");
|
||||||
|
fflush(pipeRead);
|
||||||
|
|
||||||
setCriticalHandler(&criticalHandler);
|
setCriticalHandler(&criticalHandler);
|
||||||
|
|
||||||
critical("This critical should be displayed.");
|
critical("This critical should be displayed.");
|
||||||
|
checkBool(hasData(pipefd[0]), "data read (crititcal)");
|
||||||
|
fflush(pipeRead);
|
||||||
|
|
||||||
|
fclose(pipeWrite);
|
||||||
|
fclose(pipeRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile int counter = 0;
|
||||||
|
void timerThread() {
|
||||||
|
counter++;
|
||||||
|
}
|
||||||
|
void testTimers() {
|
||||||
|
timer_t timer = timer_createThreadTimer(&timerThread);
|
||||||
|
if (timer == NULL) {
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (timer_startInterval(timer, 10) < 0) {
|
||||||
|
showError();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
sleep(1);
|
||||||
|
timer_stop(timer);
|
||||||
|
timer_destroy(timer);
|
||||||
|
|
||||||
|
checkInt(counter, 100, "interval count");
|
||||||
}
|
}
|
||||||
|
|
||||||
handler_t handlerGetter(struct metaData metaData, const char* host) {
|
handler_t handlerGetter(struct metaData metaData, const char* host) {
|
||||||
|
@ -115,24 +187,21 @@ void testNetworking() {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void test(const char* name, void (*testFunction)()) {
|
||||||
|
printf("%s\n", name);
|
||||||
|
printf("%.*s\n", (int) strlen(name),
|
||||||
|
"===================================");
|
||||||
|
testFunction();
|
||||||
|
if (!global)
|
||||||
|
overall = false;
|
||||||
|
printf("%s: %s\n\n", name, global ? "OK" : "FAILED");
|
||||||
|
global = true;
|
||||||
|
}
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
bool overall = true;
|
test("linked lists", &testLinkedList);
|
||||||
|
test("logging", &testLogging);
|
||||||
printf("linked lists\n");
|
test("signals", &testTimers);
|
||||||
printf("============\n\n");
|
|
||||||
testLinkedList();
|
|
||||||
if (!global)
|
|
||||||
overall = false;
|
|
||||||
printf("linked lists: %s\n\n", global ? "OK" : "FAILED");
|
|
||||||
global = true;
|
|
||||||
|
|
||||||
printf("logging\n");
|
|
||||||
printf("============\n\n");
|
|
||||||
testLogging();
|
|
||||||
if (!global)
|
|
||||||
overall = false;
|
|
||||||
printf("logging: %s\n\n", global ? "OK" : "FAILED");
|
|
||||||
global = true;
|
|
||||||
|
|
||||||
|
|
||||||
printf("\nOverall: %s\n", overall ? "OK" : "FAILED");
|
printf("\nOverall: %s\n", overall ? "OK" : "FAILED");
|
||||||
|
|
Loading…
Reference in a new issue