mirror of
https://github.com/troglobit/libuev.git
synced 2026-10-20 10:59:31 +00:00
Relocate tests/ -> test/
For my own sanity, test/ is used in every other project of mine. Signed-off-by: Joachim Wiberg <troglobit@gmail.com>
This commit is contained in:
1 parent
d7a8c7895b
commit
caa62910db
12 files changed
+6
-6
No files matched your search
@@ -0,0 +1,9 @@
|
||||
*.trs
|
||||
*.log
|
||||
active
|
||||
api
|
||||
complete
|
||||
cronrun
|
||||
signal
|
||||
timer
|
||||
event
|
||||
@@ -0,0 +1,16 @@
|
||||
EXTRA_DIST = check.h
|
||||
CLEANFILES = *~ *.trs *.log
|
||||
|
||||
TESTS =
|
||||
TESTS += active
|
||||
TESTS += api
|
||||
TESTS += complete
|
||||
TESTS += cronrun
|
||||
TESTS += signal
|
||||
TESTS += timer
|
||||
TESTS += event
|
||||
|
||||
check_PROGRAMS = $(TESTS)
|
||||
|
||||
CPPFLAGS = -D_GNU_SOURCE
|
||||
LDADD = -L../src ../src/libuev.la
|
||||
@@ -0,0 +1,64 @@
|
||||
#include "check.h"
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define TIMEOUT1 2 /* 2 sec */
|
||||
#define TIMEOUT2 4 /* 4 sec */
|
||||
#define DAYLY (24 * 60 * 60) /* Seconds in one day */
|
||||
|
||||
uev_t timer1;
|
||||
uev_t timer2;
|
||||
uev_t timer3;
|
||||
uev_t cron1;
|
||||
uev_t cron2;
|
||||
|
||||
static void cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
if (UEV_ERROR == events)
|
||||
fprintf(stderr, "timer watcher failed, ignoring ...\n");
|
||||
|
||||
fail_unless(w == &timer1);
|
||||
|
||||
fail_unless(uev_timer_active(&timer2));
|
||||
fail_unless(!uev_timer_active(&timer3));
|
||||
fail_unless(uev_cron_active(&cron1));
|
||||
fail_unless(uev_cron_active(&cron2));
|
||||
|
||||
uev_timer_stop(&timer2);
|
||||
uev_timer_stop(&cron2);
|
||||
|
||||
fail_unless(!uev_timer_active(&timer2));
|
||||
fail_unless(!uev_cron_active(&cron2));
|
||||
|
||||
/* Restart timer and see if we fail in uev_exit() */
|
||||
uev_timer_start(&timer2);
|
||||
|
||||
uev_exit(w->ctx);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
struct timeval tomorrow;
|
||||
uev_ctx_t ctx;
|
||||
|
||||
gettimeofday(&tomorrow, NULL);
|
||||
tomorrow.tv_sec += 24 * 60 * 60;
|
||||
|
||||
uev_init(&ctx);
|
||||
uev_timer_init(&ctx, &timer1, cb, NULL, TIMEOUT1 * 1000, 0);
|
||||
uev_timer_init(&ctx, &timer2, cb, NULL, TIMEOUT2 * 1000, 0);
|
||||
uev_timer_init(&ctx, &timer3, cb, NULL, TIMEOUT2 * 1000, 0);
|
||||
uev_timer_stop(&timer3);
|
||||
|
||||
uev_cron_init(&ctx, &cron1, cb, NULL, tomorrow.tv_sec, 24 * 60 * 60);
|
||||
uev_cron_init(&ctx, &cron2, cb, NULL, tomorrow.tv_sec, 24 * 60 * 60);
|
||||
|
||||
return uev_run(&ctx, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
#include "check.h"
|
||||
|
||||
uev_t timer, file;
|
||||
int counter = 10;
|
||||
|
||||
static void cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
if (UEV_ERROR == events)
|
||||
fprintf(stderr, "timer watcher failed, ignoring ...\n");
|
||||
|
||||
if (counter--)
|
||||
return;
|
||||
|
||||
uev_exit(w->ctx);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uev_ctx_t ctx;
|
||||
FILE *fp;
|
||||
|
||||
uev_init(&ctx);
|
||||
uev_timer_init(&ctx, &timer, cb, NULL, 100, 100);
|
||||
|
||||
fp = fopen("/dev/one", "r");
|
||||
if (fp)
|
||||
uev_io_init(&ctx, &file, cb, NULL, fileno(fp), UEV_READ);
|
||||
|
||||
uev_run(&ctx, 0);
|
||||
|
||||
uev_exit(&ctx); /* Should not hang event loop, troglobit/uftpd#16 */
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#ifndef UEV_TEST_CHECK_H_
|
||||
#define UEV_TEST_CHECK_H_
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "../src/uev.h"
|
||||
|
||||
#define fail_unless(test) \
|
||||
do { \
|
||||
if (!(test)) { \
|
||||
fprintf(stderr, \
|
||||
"----------------------------------------------\n" \
|
||||
"%s:%d: test FAILED:\nFailed test: %s\n" \
|
||||
"----------------------------------------------\n", \
|
||||
__FILE__, __LINE__, #test); \
|
||||
exit(1); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static inline int test(int result, const char *fmt, ...)
|
||||
{
|
||||
char buf[80];
|
||||
size_t len;
|
||||
va_list ap;
|
||||
const char success[] = " \033[1m[ OK ]\033[0m\n";
|
||||
const char failure[] = " \033[7m[FAIL]\033[0m\n";
|
||||
const char dots[] = " .....................................................................";
|
||||
|
||||
va_start(ap, fmt);
|
||||
len = vsnprintf(buf, sizeof(buf), fmt, ap);
|
||||
va_end(ap);
|
||||
|
||||
write(STDERR_FILENO, buf, len);
|
||||
write(STDERR_FILENO, dots, 60 - len); /* pad with dots. */
|
||||
|
||||
if (!result)
|
||||
write(STDERR_FILENO, success, strlen(success));
|
||||
else
|
||||
write(STDERR_FILENO, failure, strlen(failure));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline int timespec_newer(const struct timespec *a, const struct timespec *b)
|
||||
{
|
||||
if (a->tv_sec != b->tv_sec)
|
||||
return a->tv_sec > b->tv_sec;
|
||||
|
||||
return a->tv_nsec > b->tv_nsec;
|
||||
}
|
||||
|
||||
static inline char *timespec2str(struct timespec *ts, char *buf, size_t len)
|
||||
{
|
||||
size_t ret, pos;
|
||||
struct tm t;
|
||||
|
||||
memset(buf, 0, len);
|
||||
|
||||
tzset();
|
||||
if (localtime_r(&(ts->tv_sec), &t) == NULL)
|
||||
return buf;
|
||||
|
||||
ret = strftime(buf, len, "%F %T", &t);
|
||||
if (ret == 0)
|
||||
return buf;
|
||||
len -= ret - 1;
|
||||
|
||||
pos = strlen(buf);
|
||||
len -= pos;
|
||||
snprintf(&buf[pos], len, ".%09ld", ts->tv_nsec);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif /* UEV_TEST_CHECK_H_ */
|
||||
+180
@@ -0,0 +1,180 @@
|
||||
/* Test libuEv event library
|
||||
*
|
||||
* Copyright (c) 2012 Flemming Madsen <flemming!madsen()madsensoft!dk>
|
||||
* Copyright (c) 2013-2021 Joachim Wiberg <troglobit()gmail!com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "check.h"
|
||||
#include <signal.h>
|
||||
|
||||
typedef struct {
|
||||
int counter;
|
||||
} my_t;
|
||||
|
||||
static int in, out;
|
||||
static int period = 0;
|
||||
static uev_t *watchdog;
|
||||
|
||||
static void lifetime_cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
if (UEV_ERROR == events)
|
||||
fprintf(stderr, "timer watcher failed, ignoring ...\n");
|
||||
|
||||
fprintf(stderr, "\nLifetime exceeded, program completed successfully! (arg:%p)\n", arg);
|
||||
uev_exit(w->ctx);
|
||||
}
|
||||
|
||||
/* The pipe watchdog, if it triggers we haven't received data in time. */
|
||||
static void timeout_cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
if (UEV_ERROR == events)
|
||||
fprintf(stderr, "timer watcher failed, ignoring ...\n");
|
||||
|
||||
watchdog = NULL;
|
||||
fprintf(stderr, "\nTimeout exceeded %p\n", arg);
|
||||
|
||||
// uev_timer_stop(w); <-- No need to stop timers with period=0 :)
|
||||
uev_exit(w->ctx);
|
||||
}
|
||||
|
||||
static void periodic_task(uev_t *w, void *arg, int events)
|
||||
{
|
||||
fprintf(stderr, "|");
|
||||
}
|
||||
|
||||
static void signal_cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
if (UEV_ERROR == events) {
|
||||
fprintf(stderr, "Signal watcher failed, unrecoverable error.\n");
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, w->signo == SIGINT ? "^Cv" : "^\v");
|
||||
}
|
||||
|
||||
static void pipe_read_cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
int len;
|
||||
char msg[50];
|
||||
|
||||
if (UEV_ERROR == events) {
|
||||
error:
|
||||
fprintf(stderr, "pipe watcher failed, restarting ...\n");
|
||||
uev_io_start(w);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Kick watchdog */
|
||||
if (watchdog)
|
||||
uev_timer_set(watchdog, 1000, 0);
|
||||
|
||||
/* Here we can read() from in or w->fd, either works. */
|
||||
len = read(w->fd, msg, sizeof(msg));
|
||||
if (len < 0) {
|
||||
perror(__func__);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (len == 0 || UEV_HUP == events) {
|
||||
fprintf(stderr, "Other end of pipe closed, no more data\n");
|
||||
return;
|
||||
}
|
||||
|
||||
// fprintf(stderr, "READ %.*s %d\n", len, msg, len);
|
||||
fprintf(stderr, "%.*s.%d ", len, msg, len);
|
||||
}
|
||||
|
||||
static void pipe_write_cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
my_t *my = arg;
|
||||
char *msg = "TESTING";
|
||||
|
||||
if (UEV_ERROR == events)
|
||||
fprintf(stderr, "timer watcher failed, ignoring ...\n");
|
||||
|
||||
/* Here we *must* use out, not w->fd, since we're a timer callback */
|
||||
if (write(out, msg, my->counter) < 0) {
|
||||
perror("\nFailed writing to pipe");
|
||||
return;
|
||||
}
|
||||
|
||||
// fprintf(stderr, "WRITE %.*s %d\n", my->counter, msg, my->counter);
|
||||
fprintf(stderr, "%d ", my->counter);
|
||||
period = my->counter + 5;
|
||||
my->counter++;
|
||||
|
||||
uev_timer_set(w, period * 100, 0);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
int fd[2];
|
||||
my_t my = { .counter = 1 };
|
||||
uev_t timeout, wdt, periodic, writer, reader, sigint_watcher, sigquit_watcher;
|
||||
uev_ctx_t ctx;
|
||||
|
||||
/* Work load, one timer callback writes to a pipe periodically,
|
||||
* and one I/O watcher that is called every time the pipe has
|
||||
* some data. */
|
||||
if (pipe(fd) < 0)
|
||||
return 1;
|
||||
|
||||
/* Initialize libuEv */
|
||||
uev_init(&ctx);
|
||||
|
||||
/* Signal watchers, Ctrl-C => SIGINT, Ctrl-\ => SIGQUIT */
|
||||
uev_signal_init(&ctx, &sigint_watcher, signal_cb, NULL, SIGINT);
|
||||
uev_signal_init(&ctx, &sigquit_watcher, signal_cb, NULL, SIGQUIT);
|
||||
|
||||
/* Total program execution time */
|
||||
uev_timer_init(&ctx, &timeout, lifetime_cb, (void *)(intptr_t)2, 4000, 0);
|
||||
|
||||
/* Main pipe worker and consumer */
|
||||
in = fd[0];
|
||||
out = fd[1];
|
||||
uev_io_init(&ctx, &reader, pipe_read_cb, NULL, in, UEV_READ);
|
||||
uev_timer_init(&ctx, &writer, pipe_write_cb, &my, 400, 0);
|
||||
|
||||
/*
|
||||
* Watchdog for the above timer callback, if it doesn't wake up
|
||||
* and write to the pipe within a given deadline it will bark.
|
||||
*/
|
||||
uev_timer_init(&ctx, &wdt, timeout_cb, (void *)(intptr_t)1, 950, 0);
|
||||
watchdog = &wdt;
|
||||
|
||||
/* Periodic background task */
|
||||
uev_timer_init(&ctx, &periodic, periodic_task, NULL, 200, 200);
|
||||
|
||||
/* Start event loop */
|
||||
uev_run(&ctx, 0);
|
||||
|
||||
fprintf(stderr, "Period is %d must be 10: %s\n", period, 10 == period ? "OK" : "ERROR!");
|
||||
fail_unless(10 == period);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,84 @@
|
||||
/* Test cron API in libuEv event library
|
||||
*
|
||||
* Copyright (c) 2016-2021 Joachim Wiberg <troglobit()gmail!com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "check.h"
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define TIMEOUT 2
|
||||
#define INTERVAL 2
|
||||
|
||||
int result = -1;
|
||||
struct timeval tv;
|
||||
|
||||
static void cron_job(uev_t *w, void *arg, int events)
|
||||
{
|
||||
struct timeval now;
|
||||
static int laps = 3;
|
||||
|
||||
if (UEV_ERROR == events)
|
||||
fprintf(stderr, "cron watcher failed, ignoring ...\n");
|
||||
|
||||
/* Update timer every lap */
|
||||
tv.tv_sec += TIMEOUT;
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
printf("Cron job HELO %s", ctime(&now.tv_sec));
|
||||
fail_unless(now.tv_sec == tv.tv_sec);
|
||||
|
||||
if (!laps--) {
|
||||
result = 0;
|
||||
uev_exit(w->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uev_ctx_t ctx;
|
||||
time_t when, interval;
|
||||
uev_t cron;
|
||||
int rc;
|
||||
|
||||
uev_init(&ctx);
|
||||
|
||||
gettimeofday(&tv, NULL);
|
||||
when = tv.tv_sec + TIMEOUT;
|
||||
|
||||
printf("Start of test %s", ctime(&tv.tv_sec));
|
||||
printf("Expected cron %s", ctime(&when));
|
||||
|
||||
interval = INTERVAL;
|
||||
uev_cron_init(&ctx, &cron, cron_job, NULL, when, interval);
|
||||
|
||||
rc = uev_run(&ctx, 0);
|
||||
fail_unless(result == 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,78 @@
|
||||
/* Verifies eventfd support
|
||||
*
|
||||
* Copyright (c) 2018-2021 Joachim Wiberg <troglobit@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "check.h"
|
||||
#include <err.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#define LAPS 10
|
||||
pid_t pid;
|
||||
|
||||
static void cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
static int num = LAPS;
|
||||
|
||||
num--;
|
||||
// printf("Got event %d ...\n", LAPS - num);
|
||||
if (num == 0) {
|
||||
waitpid(pid, NULL, 0);
|
||||
uev_exit(w->ctx);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uev_ctx_t ctx;
|
||||
uev_t ev;
|
||||
int i;
|
||||
|
||||
/* Initialize libuEv */
|
||||
uev_init(&ctx);
|
||||
|
||||
/* Setup callbacks */
|
||||
uev_event_init(&ctx, &ev, cb, NULL);
|
||||
|
||||
pid = fork();
|
||||
if (-1 == pid)
|
||||
err(1, "fork");
|
||||
|
||||
/* Start event loop */
|
||||
if (pid > 0)
|
||||
return uev_run(&ctx, 0);
|
||||
|
||||
for (i = 0; i < LAPS; i++) {
|
||||
uev_event_post(&ev);
|
||||
usleep(10000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
+149
@@ -0,0 +1,149 @@
|
||||
/* Multiple signals, segfault and fork() to test sub-processes.
|
||||
*
|
||||
* Copyright (c) 2015-2021 Joachim Wiberg <troglobit@gmail.com>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
* THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "check.h"
|
||||
#include <err.h>
|
||||
#include <sched.h>
|
||||
#include <signal.h>
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#define DO_SEGFAULT 1
|
||||
|
||||
typedef struct {
|
||||
pid_t pid;
|
||||
int magic;
|
||||
void *ptr;
|
||||
} arg_t;
|
||||
|
||||
/* Stack is not shared between parent and child, only the heap. */
|
||||
static arg_t arg = {
|
||||
.magic = 1337,
|
||||
.ptr = NULL
|
||||
};
|
||||
|
||||
static int callback(arg_t *arg, int event, void *foo)
|
||||
{
|
||||
arg_t *event_arg = (arg_t *)foo;
|
||||
|
||||
printf("child[%d] magic %d ptr %p, event %d event arg %p\n",
|
||||
getpid(), arg->magic, arg->ptr, event, event_arg);
|
||||
|
||||
arg->magic = 7331;
|
||||
arg->ptr = &event_arg;
|
||||
|
||||
/* Cause segfault! */
|
||||
#if DO_SEGFAULT == 1
|
||||
event_arg->ptr = arg->ptr;
|
||||
printf("child: segfaulting failed!\n");
|
||||
#endif
|
||||
|
||||
return 42;
|
||||
}
|
||||
|
||||
static void sig_cb(uev_t *w, void *cbarg, int events)
|
||||
{
|
||||
arg_t *arg = (arg_t *)cbarg;
|
||||
|
||||
switch (w->signo) {
|
||||
case SIGSEGV:
|
||||
// printf("Got SIGSEGV (%d) from PID %d\n", w->siginfo.ssi_signo, w->siginfo.ssi_pid);
|
||||
warnx("PID %d caused segfault.", getpid());
|
||||
exit(-1);
|
||||
break;
|
||||
|
||||
case SIGCHLD:
|
||||
if (arg->pid != w->siginfo.ssi_pid)
|
||||
err(1, "wrong child exited pid %d vs ssi_pid %d",
|
||||
arg->pid, w->siginfo.ssi_pid);
|
||||
|
||||
warnx("Got SIGCHLD (%d), PID %d exited, bye.", w->siginfo.ssi_signo, arg->pid);
|
||||
break;
|
||||
|
||||
default:
|
||||
err(1, "unhandled signal %d", w->siginfo.ssi_signo);
|
||||
}
|
||||
}
|
||||
|
||||
static void work_cb(uev_t *w, void *cbarg, int events)
|
||||
{
|
||||
arg_t *arg = (arg_t *)cbarg;
|
||||
pid_t pid;
|
||||
int rc = 0;
|
||||
|
||||
pid = fork();
|
||||
if (-1 == pid)
|
||||
err(1, "fork");
|
||||
if (!pid)
|
||||
exit(callback(arg, 6137, NULL));
|
||||
|
||||
arg->pid = pid;
|
||||
pid = waitpid(pid, &rc, 0);
|
||||
if (pid == -1)
|
||||
err(1, "waitpid");
|
||||
|
||||
if (WIFEXITED(rc))
|
||||
printf("Child %d exited normally => %d\n", pid, WEXITSTATUS(rc));
|
||||
else if (WCOREDUMP(rc))
|
||||
printf("Child %d crashed%s\n", pid, DO_SEGFAULT
|
||||
? ", as expected, everything is OK."
|
||||
: ". This should not happen!");
|
||||
else
|
||||
printf("Child %d did not exit normally!\n", pid);
|
||||
}
|
||||
|
||||
static void exit_cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
printf("Process deadline reached, exiting!\n");
|
||||
uev_exit(w->ctx);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uev_t deadline, sigsegv, sigchld, timeout;
|
||||
uev_ctx_t ctx;
|
||||
|
||||
/* Initialize libuEv */
|
||||
uev_init(&ctx);
|
||||
|
||||
/* Setup callbacks */
|
||||
uev_signal_init(&ctx, &sigsegv, sig_cb, NULL, SIGSEGV);
|
||||
uev_signal_init(&ctx, &sigchld, sig_cb, &arg, SIGCHLD);
|
||||
uev_timer_init(&ctx, &timeout, work_cb, &arg, 400, 0);
|
||||
uev_timer_init(&ctx, &deadline, exit_cb, NULL, 1000, 0);
|
||||
|
||||
/* Start event loop */
|
||||
return uev_run(&ctx, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
@@ -0,0 +1,45 @@
|
||||
#include "check.h"
|
||||
#include <time.h>
|
||||
#include <sys/time.h>
|
||||
|
||||
#define TIMEOUT 2 /* 2 sec */
|
||||
|
||||
int result = -1;
|
||||
struct timeval start;
|
||||
|
||||
static void cb(uev_t *w, void *arg, int events)
|
||||
{
|
||||
struct timeval now;
|
||||
|
||||
if (UEV_ERROR == events)
|
||||
fprintf(stderr, "timer watcher failed, ignoring ...\n");
|
||||
|
||||
gettimeofday(&now, NULL);
|
||||
fail_unless(now.tv_sec == start.tv_sec + TIMEOUT);
|
||||
|
||||
result = 0;
|
||||
uev_exit(w->ctx);
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
uev_ctx_t ctx;
|
||||
uev_t w;
|
||||
int rc;
|
||||
|
||||
uev_init(&ctx);
|
||||
uev_timer_init(&ctx, &w, cb, NULL, TIMEOUT * 1000, 0);
|
||||
gettimeofday(&start, NULL);
|
||||
|
||||
rc = uev_run(&ctx, 0);
|
||||
fail_unless(result == 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Local Variables:
|
||||
* indent-tabs-mode: t
|
||||
* c-file-style: "linux"
|
||||
* End:
|
||||
*/
|
||||
Reference in new issue
Block a user