summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorSimon Rettberg2016-02-05 15:05:30 +0100
committerSimon Rettberg2016-02-05 15:05:30 +0100
commit627645acc074eab7a3694a267bc2a643d8b3e57a (patch)
tree5f61225803c369ab1295ce0ee36a33ae6cb51eb8 /src
parent[SERVER] BREAKING: Get rid of pseudo case-insensitivity (diff)
downloaddnbd3-627645acc074eab7a3694a267bc2a643d8b3e57a.tar.gz
dnbd3-627645acc074eab7a3694a267bc2a643d8b3e57a.tar.xz
dnbd3-627645acc074eab7a3694a267bc2a643d8b3e57a.zip
First steps in make signals more abstract from the underlying mechanism; replace epoll with poll.
We now don't assume that a signal equals a single fd (eventfd on Linux). The next step would be to create a version of signal.c that uses a pipe internally, so it can be used on other platforms, like *BSD. This is also the reason epoll was replaced with poll in uplink.c
Diffstat (limited to 'src')
-rw-r--r--src/fuse/connection.c16
-rw-r--r--src/fuse/connection.h3
-rw-r--r--src/fuse/main.c6
-rw-r--r--src/server/altservers.c21
-rw-r--r--src/server/globals.h3
-rw-r--r--src/server/locks.c4
-rw-r--r--src/server/threadpool.c18
-rw-r--r--src/server/uplink.c121
-rw-r--r--src/shared/signal.c42
-rw-r--r--src/shared/signal.h31
10 files changed, 136 insertions, 129 deletions
diff --git a/src/fuse/connection.c b/src/fuse/connection.c
index 170e329..65483a5 100644
--- a/src/fuse/connection.c
+++ b/src/fuse/connection.c
@@ -46,7 +46,7 @@ static struct {
static struct {
int sockFd;
pthread_mutex_t sendMutex;
- int panicSignalFd;
+ dnbd3_signal_t* panicSignal;
dnbd3_host_t currentServer;
uint64_t startupTime;
} connection;
@@ -134,7 +134,7 @@ bool connection_init(const char *hosts, const char *lowerImage, const uint16_t r
image.rid = remoteRid;
image.size = remoteSize;
connection.currentServer = altservers[i].host;
- connection.panicSignalFd = signal_new();
+ connection.panicSignal = signal_new();
connection.startupTime = nowMilli();
connection.sockFd = sock;
requests.head = NULL;
@@ -205,7 +205,7 @@ bool connection_read(dnbd3_async_t *request)
shutdown( connection.sockFd, SHUT_RDWR );
connection.sockFd = -1;
pthread_mutex_unlock( &connection.sendMutex );
- signal_call( connection.panicSignalFd );
+ signal_call( connection.panicSignal );
return true;
}
}
@@ -316,7 +316,7 @@ static void* connection_receiveThreadMain(void *sockPtr)
// Success, wake up caller
request->success = true;
request->finished = true;
- signal_call( request->signalFd );
+ signal_call( request->signal );
}
} else if ( reply.cmd == CMD_GET_SERVERS ) {
// List of known alt servers
@@ -348,7 +348,7 @@ fail:;
logadd( LOG_DEBUG1, "RT: Local sock: %d, global: %d", sockFd, connection.sockFd );
if ( connection.sockFd == sockFd ) {
connection.sockFd = -1;
- signal_call( connection.panicSignalFd );
+ signal_call( connection.panicSignal );
}
pthread_mutex_unlock( &connection.sendMutex );
// As we're the only reader, it's safe to close the socket now
@@ -365,7 +365,7 @@ static void* connection_backgroundThread(void *something UNUSED)
const uint64_t now = nowMilli();
if ( now < nextKeepalive && now < nextRttCheck ) {
int waitTime = (int)( MIN( nextKeepalive, nextRttCheck ) - now );
- int waitRes = signal_wait( connection.panicSignalFd, waitTime );
+ int waitRes = signal_wait( connection.panicSignal, waitTime );
if ( waitRes == SIGNAL_ERROR ) {
logadd( LOG_WARNING, "Error waiting on signal in background thread! Errno = %d", errno );
}
@@ -585,7 +585,7 @@ static void switchConnection(int sockFd, alt_server_t *srv)
if ( ret != 0 ) {
close( sockFd );
logadd( LOG_WARNING, "Could not getpeername after connection switch, assuming connection already dead again. (Errno=%d)", errno );
- signal_call( connection.panicSignalFd );
+ signal_call( connection.panicSignal );
return;
}
connection.startupTime = nowMilli();
@@ -604,7 +604,7 @@ static void switchConnection(int sockFd, alt_server_t *srv)
logadd( LOG_WARNING, "Resending pending request failed, re-entering panic mode" );
shutdown( connection.sockFd, SHUT_RDWR );
connection.sockFd = -1;
- signal_call( connection.panicSignalFd );
+ signal_call( connection.panicSignal );
}
}
pthread_mutex_unlock( &connection.sendMutex );
diff --git a/src/fuse/connection.h b/src/fuse/connection.h
index 06db6c4..f01577d 100644
--- a/src/fuse/connection.h
+++ b/src/fuse/connection.h
@@ -1,6 +1,7 @@
#ifndef _CONNECTION_H_
#define _CONNECTION_H_
+#include "../shared/signal.h"
#include <stdbool.h>
#include <stdint.h>
@@ -11,7 +12,7 @@ typedef struct _dnbd3_async {
char* buffer; // Caller-provided buffer to be filled
uint64_t offset;
uint32_t length;
- int signalFd; // Used to signal the caller
+ dnbd3_signal_t* signal; // Used to signal the caller
bool finished; // Will be set to true if the request has been handled
bool success; // Will be set to true if the request succeeded
} dnbd3_async_t;
diff --git a/src/fuse/main.c b/src/fuse/main.c
index 22c400e..cf35596 100644
--- a/src/fuse/main.c
+++ b/src/fuse/main.c
@@ -136,13 +136,13 @@ static int image_read(const char *path, char *buf, size_t size, off_t offset, st
request.buffer = buf;
request.length = (uint32_t)size;
request.offset = offset;
- request.signalFd = signal_newBlocking();
+ request.signal = signal_newBlocking();
if ( !connection_read( &request ) ) {
return -EINVAL;
}
while ( !request.finished ) {
- int ret = signal_wait( request.signalFd, 5000 );
+ int ret = signal_wait( request.signal, 5000 );
if ( !keepRunning ) {
connection_close();
break;
@@ -151,7 +151,7 @@ static int image_read(const char *path, char *buf, size_t size, off_t offset, st
debugf( "fuse_read signal wait returned %d", ret );
}
}
- signal_close( request.signalFd );
+ signal_close( request.signal );
if ( request.success ) {
return request.length;
} else {
diff --git a/src/server/altservers.c b/src/server/altservers.c
index e4a7dca..4ebf2f6 100644
--- a/src/server/altservers.c
+++ b/src/server/altservers.c
@@ -21,7 +21,7 @@
static dnbd3_connection_t *pending[SERVER_MAX_PENDING_ALT_CHECKS];
static pthread_spinlock_t pendingLockWrite; // Lock for adding something to pending. (NULL -> nonNULL)
static pthread_mutex_t pendingLockConsume = PTHREAD_MUTEX_INITIALIZER; // Lock for removing something (nonNULL -> NULL)
-static int signalFd = -1;
+static dnbd3_signal_t* runSignal = NULL;
static dnbd3_alt_server_t altServers[SERVER_MAX_ALTS];
static int numAltServers = 0;
@@ -53,7 +53,7 @@ void altservers_init()
void altservers_shutdown()
{
if ( !initDone ) return;
- signal_call( signalFd ); // Wake altservers thread up
+ signal_call( runSignal ); // Wake altservers thread up
thread_join( altThread, NULL );
}
@@ -154,7 +154,7 @@ void altservers_findUplink(dnbd3_connection_t *uplink)
pending[i] = uplink;
uplink->rttTestResult = RTT_INPROGRESS;
spin_unlock( &pendingLockWrite );
- signal_call( signalFd ); // Wake altservers thread up
+ signal_call( runSignal ); // Wake altservers thread up
return;
}
// End of loop - no free slot
@@ -365,16 +365,16 @@ static void *altservers_main(void *data UNUSED)
for (int i = 0; i < SERVER_MAX_PENDING_ALT_CHECKS; ++i)
pending[i] = NULL;
spin_unlock( &pendingLockWrite );
- // Init signal-pipe
- signalFd = signal_new();
- if ( signalFd < 0 ) {
+ // Init signal
+ runSignal = signal_new();
+ if ( runSignal == NULL ) {
logadd( LOG_WARNING, "error creating signal object. Uplink feature unavailable." );
goto cleanup;
}
// LOOP
while ( !_shutdown ) {
// Wait 5 seconds max.
- ret = signal_wait( signalFd, 5000 );
+ ret = signal_wait( runSignal, 5000 );
if ( _shutdown ) goto cleanup;
if ( ret == SIGNAL_ERROR ) {
if ( errno == EAGAIN || errno == EINTR ) continue;
@@ -511,8 +511,7 @@ static void *altservers_main(void *data UNUSED)
uplink->betterServer = servers[bestIndex];
uplink->rttTestResult = RTT_DOCHANGE;
spin_unlock( &uplink->rttLock );
- static uint64_t counter = 1;
- write( uplink->signal, &counter, sizeof(counter) );
+ signal_call( uplink->signal );
} else if (bestSock == -1) {
// No server was reachable
spin_lock( &uplink->rttLock );
@@ -540,8 +539,8 @@ static void *altservers_main(void *data UNUSED)
}
}
cleanup: ;
- if ( signalFd != -1 ) signal_close( signalFd );
- signalFd = -1;
+ if ( runSignal != NULL ) signal_close( runSignal );
+ runSignal = NULL;
return NULL ;
}
diff --git a/src/server/globals.h b/src/server/globals.h
index b0380fa..6f9652b 100644
--- a/src/server/globals.h
+++ b/src/server/globals.h
@@ -2,6 +2,7 @@
#define _GLOBALS_H_
#include "../types.h"
+#include "../shared/signal.h"
#include <stdint.h>
#include <time.h>
#include <pthread.h>
@@ -42,7 +43,7 @@ typedef struct
struct _dnbd3_connection
{
int fd; // socket fd to remote server
- int signal; // eventfd used to wake up the process
+ dnbd3_signal_t* signal; // used to wake up the process
pthread_t thread; // thread holding the connection
pthread_spinlock_t queueLock; // lock for synchronization on request queue etc.
dnbd3_queued_request_t queue[SERVER_MAX_UPLINK_QUEUE];
diff --git a/src/server/locks.c b/src/server/locks.c
index bc8b18e..294f862 100644
--- a/src/server/locks.c
+++ b/src/server/locks.c
@@ -50,7 +50,7 @@ static int init_done = 0;
static pthread_spinlock_t initdestory;
static int lockId = 0;
static pthread_t watchdog = 0;
-static int watchdogSignal = -1;
+static dnbd3_signal_t* watchdogSignal = NULL;
static void *debug_thread_watchdog(void *something);
@@ -278,7 +278,7 @@ static void *debug_thread_watchdog(void *something UNUSED)
}
pthread_spin_unlock( &initdestory );
}
- if ( watchdogSignal == -1 || signal_wait( watchdogSignal, 5000 ) == SIGNAL_ERROR ) sleep( 5 );
+ if ( watchdogSignal == NULL || signal_wait( watchdogSignal, 5000 ) == SIGNAL_ERROR ) sleep( 5 );
}
return NULL ;
}
diff --git a/src/server/threadpool.c b/src/server/threadpool.c
index b1c46a3..12cbe03 100644
--- a/src/server/threadpool.c
+++ b/src/server/threadpool.c
@@ -10,7 +10,7 @@
typedef struct _entry_t {
struct _entry_t *next;
pthread_t thread;
- int signalFd;
+ dnbd3_signal_t* signal;
void *(*startRoutine)(void *);
void * arg;
} entry_t;
@@ -43,7 +43,7 @@ void threadpool_close()
while ( ptr != NULL ) {
entry_t *current = ptr;
ptr = ptr->next;
- signal_call( current->signalFd );
+ signal_call( current->signal );
}
spin_unlock( &poolLock );
spin_destroy( &poolLock );
@@ -61,15 +61,15 @@ bool threadpool_run(void *(*startRoutine)(void *), void *arg)
logadd( LOG_WARNING, "Could not alloc entry_t for new thread\n" );
return false;
}
- entry->signalFd = signal_newBlocking();
- if ( entry->signalFd < 0 ) {
- logadd( LOG_WARNING, "Could not create signalFd for new thread pool thread\n" );
+ entry->signal = signal_newBlocking();
+ if ( entry->signal == NULL ) {
+ logadd( LOG_WARNING, "Could not create signal for new thread pool thread\n" );
free( entry );
return false;
}
if ( 0 != thread_create( &(entry->thread), &threadAttrs, threadpool_worker, (void*)entry ) ) {
logadd( LOG_WARNING, "Could not create new thread for thread pool\n" );
- signal_close( entry->signalFd );
+ signal_close( entry->signal );
free( entry );
return false;
}
@@ -77,7 +77,7 @@ bool threadpool_run(void *(*startRoutine)(void *), void *arg)
entry->next = NULL;
entry->startRoutine = startRoutine;
entry->arg = arg;
- signal_call( entry->signalFd );
+ signal_call( entry->signal );
return true;
}
@@ -90,7 +90,7 @@ static void *threadpool_worker(void *entryPtr)
entry_t *entry = (entry_t*)entryPtr;
for ( ;; ) {
// Wait for signal from outside that we have work to do
- int ret = signal_clear( entry->signalFd );
+ int ret = signal_clear( entry->signal );
if ( _shutdown ) break;
if ( ret > 0 ) {
if ( entry->startRoutine == NULL ) {
@@ -123,7 +123,7 @@ static void *threadpool_worker(void *entryPtr)
logadd( LOG_DEBUG1, "Unexpected return value %d for signal_wait in threadpool worker!", ret );
}
}
- signal_close( entry->signalFd );
+ signal_close( entry->signal );
free( entry );
return NULL;
}
diff --git a/src/server/uplink.c b/src/server/uplink.c
index 3f14266..d37cb4f 100644
--- a/src/server/uplink.c
+++ b/src/server/uplink.c
@@ -12,7 +12,6 @@
#include <pthread.h>
#include <sys/socket.h>
#include <string.h>
-#include <sys/epoll.h>
#include <sys/errno.h>
#include <assert.h>
#include <unistd.h>
@@ -21,6 +20,7 @@
#include <inttypes.h>
#include <zlib.h>
#include <fcntl.h>
+#include <poll.h>
static uint64_t totalBytesReceived = 0;
@@ -75,7 +75,7 @@ bool uplink_init(dnbd3_image_t *image, int sock, dnbd3_host_t *host)
link->bytesReceived = 0;
link->queueLen = 0;
link->fd = -1;
- link->signal = -1;
+ link->signal = NULL;
link->replicationHandle = 0;
spin_lock( &link->rttLock );
if ( sock >= 0 ) {
@@ -232,7 +232,9 @@ bool uplink_request(dnbd3_client_t *client, uint64_t handle, uint64_t start, uin
spin_unlock( &uplink->queueLock );
if ( foundExisting == -1 ) { // Only wake up uplink thread if the request needs to be relayed
- signal_call( uplink->signal );
+ if ( signal_call( uplink->signal ) == SIGNAL_ERROR ) {
+ logadd( LOG_WARNING, "Cannot wake up uplink thread; errno=%d", (int)errno );
+ }
}
return true;
}
@@ -243,37 +245,30 @@ bool uplink_request(dnbd3_client_t *client, uint64_t handle, uint64_t start, uin
*/
static void* uplink_mainloop(void *data)
{
- const int MAXEVENTS = 3;
- struct epoll_event ev, events[MAXEVENTS];
+#define EV_SIGNAL (0)
+#define EV_SOCKET (1)
+#define EV_COUNT (2)
+ struct pollfd events[EV_COUNT];
dnbd3_connection_t *link = (dnbd3_connection_t*)data;
- int fdEpoll = -1;
int numSocks, i, waitTime;
int altCheckInterval = SERVER_RTT_DELAY_INIT;
int discoverFailCount = 0;
time_t nextAltCheck = 0, nextKeepalive = 0;
char buffer[200];
+ memset( events, 0, sizeof(events) );
//
assert( link != NULL );
setThreadName( "idle-uplink" );
blockNoncriticalSignals();
//
- fdEpoll = epoll_create( 2 );
- if ( fdEpoll == -1 ) {
- logadd( LOG_WARNING, "epoll_create failed. Uplink unavailable." );
- goto cleanup;
- }
link->signal = signal_new();
- if ( link->signal < 0 ) {
- logadd( LOG_WARNING, "error creating pipe. Uplink unavailable." );
- goto cleanup;
- }
- memset( &ev, 0, sizeof(ev) );
- ev.events = EPOLLIN;
- ev.data.fd = link->signal;
- if ( epoll_ctl( fdEpoll, EPOLL_CTL_ADD, link->signal, &ev ) < 0 ) {
- logadd( LOG_WARNING, "adding eventfd to epoll set failed" );
+ if ( link->signal == NULL ) {
+ logadd( LOG_WARNING, "error creating signal. Uplink unavailable." );
goto cleanup;
}
+ events[EV_SIGNAL].events = POLLIN;
+ events[EV_SIGNAL].fd = signal_getWaitFd( link->signal );
+ events[EV_SOCKET].fd = -1;
while ( !_shutdown && !link->shutdown ) {
// Check if server switch is in order
spin_lock( &link->rttLock );
@@ -305,71 +300,52 @@ static void* uplink_mainloop(void *data)
// Re-send all pending requests
uplink_sendRequests( link, false );
uplink_sendReplicationRequest( link );
- memset( &ev, 0, sizeof(ev) );
- ev.events = EPOLLIN | EPOLLRDHUP | EPOLLPRI;
- ev.data.fd = link->fd;
- if ( epoll_ctl( fdEpoll, EPOLL_CTL_ADD, link->fd, &ev ) < 0 ) {
- logadd( LOG_WARNING, "adding uplink to epoll set failed" );
- goto cleanup;
- }
+ events[EV_SOCKET].events = POLLIN | POLLRDHUP;
+ events[EV_SOCKET].fd = link->fd;
nextAltCheck = time( NULL ) + altCheckInterval;
// The rtt worker already did the handshake for our image, so there's nothing
// more to do here
}
- // epoll()
+ // poll()
waitTime = (time( NULL ) - nextAltCheck) * 1000;
if ( waitTime < 1500 ) waitTime = 1500;
if ( waitTime > 5000 ) waitTime = 5000;
- numSocks = epoll_wait( fdEpoll, events, MAXEVENTS, waitTime );
+ numSocks = poll( events, EV_COUNT, waitTime );
if ( _shutdown || link->shutdown ) goto cleanup;
if ( numSocks == -1 ) { // Error?
if ( errno == EINTR ) continue;
- logadd( LOG_DEBUG1, "epoll_wait() error %d", (int)errno);
+ logadd( LOG_DEBUG1, "poll() error %d", (int)errno );
usleep( 10000 );
continue;
}
- // Check all events
- for ( i = 0; i < numSocks; ++i ) {
- // Check for errors....
- if ( (events[i].events & (EPOLLERR | EPOLLHUP | EPOLLRDHUP)) || !(events[i].events & EPOLLIN) ) {
- if ( events[i].data.fd == link->signal ) {
- logadd( LOG_WARNING, "epoll error on signal in uplink_mainloop!" );
- goto cleanup;
- }
- if ( events[i].data.fd == link->fd ) {
- link->fd = -1;
- close( events[i].data.fd );
- logadd( LOG_DEBUG1, "Uplink gone away, panic!\n" );
- } else if ( events[i].data.fd == link->signal ) {
- logadd( LOG_DEBUG1, "Error on uplink signal fd!\n" );
- } else {
- logadd( LOG_DEBUG1, "Error on unknown FD in uplink epoll\n" );
- close( events[i].data.fd );
- }
- continue;
+ // Check events
+ // Signal
+ if ( (events[EV_SIGNAL].revents & (POLLERR | POLLHUP | POLLRDHUP | POLLNVAL)) ) {
+ logadd( LOG_WARNING, "poll error on signal in uplink_mainloop!" );
+ goto cleanup;
+ } else if ( (events[EV_SIGNAL].revents & POLLIN) ) {
+ // signal triggered -> pending requests
+ if ( signal_clear( link->signal ) == SIGNAL_ERROR ) {
+ logadd( LOG_WARNING, "Errno on signal on uplink for %s! Things will break!", link->image->name );
}
- // No error, handle normally
- if ( events[i].data.fd == link->signal ) {
- // Event on the signal fd -> a client requests data
- if ( signal_clear( link->signal ) == SIGNAL_ERROR ) {
- logadd( LOG_WARNING, "Errno on eventfd on uplink for %s! Things will break!", link->image->name );
- }
- if ( link->fd != -1 ) {
- // Uplink seems fine, relay requests to it...
- uplink_sendRequests( link, true );
- }
- } else if ( events[i].data.fd == link->fd ) {
- uplink_handleReceive( link );
- if ( link->fd == -1 ) nextAltCheck = 0;
- if ( _shutdown || link->shutdown ) goto cleanup;
- } else {
- logadd( LOG_DEBUG1, "Sanity check: unknown FD ready on epoll! Closing...\n" );
- close( events[i].data.fd );
+ if ( link->fd != -1 ) {
+ // Uplink seems fine, relay requests to it...
+ uplink_sendRequests( link, true );
}
}
- // Done handling epoll sockets
- const time_t now = time( NULL );
+ // Uplink socket
+ if ( (events[EV_SOCKET].revents & (POLLERR | POLLHUP | POLLRDHUP | POLLNVAL)) ) {
+ link->fd = -1;
+ close( events[EV_SOCKET].fd );
+ events[EV_SOCKET].fd = -1;
+ logadd( LOG_DEBUG1, "Uplink gone away, panic!\n" );
+ } else if ( (events[EV_SOCKET].revents & POLLIN) ) {
+ uplink_handleReceive( link );
+ if ( link->fd == -1 ) nextAltCheck = 0;
+ if ( _shutdown || link->shutdown ) goto cleanup;
+ }
// Send keep alive if nothing is happening
+ const time_t now = time( NULL );
if ( link->fd != -1 && link->replicationHandle == 0 && now > nextKeepalive ) {
nextKeepalive = now + 20;
if ( !uplink_sendKeepalive( link->fd ) ) {
@@ -426,7 +402,7 @@ static void* uplink_mainloop(void *data)
}
spin_unlock( &link->queueLock );
if ( resend )
- uplink_sendRequests( link, true );
+ uplink_sendRequests( link, true );
}
#endif
}
@@ -436,9 +412,9 @@ static void* uplink_mainloop(void *data)
spin_lock( &link->queueLock );
link->image->uplink = NULL;
const int fd = link->fd;
- const int signal = link->signal;
+ const dnbd3_signal_t* signal = link->signal;
link->fd = -1;
- link->signal = -1;
+ link->signal = NULL;
if ( !link->shutdown ) {
link->shutdown = true;
thread_detach( link->thread );
@@ -446,8 +422,7 @@ static void* uplink_mainloop(void *data)
spin_unlock( &link->image->lock );
spin_unlock( &link->queueLock );
if ( fd != -1 ) close( fd );
- if ( signal != -1 ) signal_close( signal );
- if ( fdEpoll != -1 ) close( fdEpoll );
+ if ( signal != NULL ) signal_close( signal );
// Wait for the RTT check to finish/fail if it's in progress
while ( link->rttTestResult == RTT_INPROGRESS )
usleep( 10000 );
diff --git a/src/shared/signal.c b/src/shared/signal.c
index a0697f8..e023c49 100644
--- a/src/shared/signal.c
+++ b/src/shared/signal.c
@@ -5,25 +5,38 @@
#include <errno.h>
#include <unistd.h>
-int signal_new()
+/*
+ * Linux implementation of signals.
+ * Internally, eventfds are used for signalling, as they
+ * provide the least overhead. We don't allocate any struct
+ * ever, but cast the event fd+1 to dnbd3_signal_t*
+ * to save all the malloc() and free() calls.
+ */
+
+dnbd3_signal_t* signal_new()
{
- return eventfd( 0, EFD_NONBLOCK );
+ // On error, eventfd() returns -1, so essentially we return NULL on error.
+ // (Yes, NULL doesn't have to be 0 everywhere, but cmon)
+ return (dnbd3_signal_t*)(intptr_t)( eventfd( 0, EFD_NONBLOCK ) + 1 );
}
-int signal_newBlocking()
+dnbd3_signal_t* signal_newBlocking()
{
- return eventfd( 0, 0 );
+ return (dnbd3_signal_t*)(intptr_t)( eventfd( 0, 0 ) + 1 );
}
-int signal_call(int signalFd)
+int signal_call(const dnbd3_signal_t* const signal)
{
- if ( signalFd < 0 ) return 0;
+ if ( signal == NULL ) return SIGNAL_ERROR;
static uint64_t one = 1;
+ const int signalFd = ( (int)(intptr_t)signal ) - 1;
return write( signalFd, &one, sizeof one ) == sizeof one;
}
-int signal_wait(int signalFd, int timeoutMs)
+int signal_wait(const dnbd3_signal_t* const signal, int timeoutMs)
{
+ if ( signal == NULL ) return SIGNAL_ERROR;
+ const int signalFd = ( (int)(intptr_t)signal ) - 1;
struct pollfd ps = {
.fd = signalFd,
.events = POLLIN
@@ -32,12 +45,14 @@ int signal_wait(int signalFd, int timeoutMs)
if ( ret == 0 ) return SIGNAL_TIMEOUT;
if ( ret == -1 ) return SIGNAL_ERROR;
if ( ps.revents & ( POLLERR | POLLNVAL ) ) return SIGNAL_ERROR;
- return signal_clear( signalFd );
+ return signal_clear( signal );
}
-int signal_clear(int signalFd)
+int signal_clear(const dnbd3_signal_t* const signal)
{
+ if ( signal == NULL ) return SIGNAL_ERROR;
uint64_t ret;
+ const int signalFd = ( (int)(intptr_t)signal ) - 1;
if ( read( signalFd, &ret, sizeof ret ) != sizeof ret ) {
if ( errno == EAGAIN ) return 0;
return SIGNAL_ERROR;
@@ -45,8 +60,15 @@ int signal_clear(int signalFd)
return (int)ret;
}
-void signal_close(int signalFd)
+void signal_close(const dnbd3_signal_t* const signal)
{
+ const int signalFd = ( (int)(intptr_t)signal ) - 1;
close( signalFd );
}
+int signal_getWaitFd(const dnbd3_signal_t* const signal)
+{
+ const int signalFd = ( (int)(intptr_t)signal ) - 1;
+ return signalFd;
+}
+
diff --git a/src/shared/signal.h b/src/shared/signal.h
index 6fd2765..3eea6fb 100644
--- a/src/shared/signal.h
+++ b/src/shared/signal.h
@@ -5,23 +5,25 @@
#define SIGNAL_TIMEOUT (-2)
#define SIGNAL_ERROR (-1)
+typedef struct _dnbd3_signal dnbd3_signal_t;
+
/**
- * Create a new signal fd (eventfd), nonblocking.
- * @return >= 0 on success, which is the fd; < 0 on error
+ * Create a new signal, nonblocking.
+ * @return NULL on error, pointer to dnbd3_signal_t on success.
*/
-int signal_new();
+dnbd3_signal_t* signal_new();
/**
- * Create a new signal fd (eventfd), blocking.
- * @return >= 0 on success, which is the fd; < 0 on error
+ * Create a new signal, blocking.
+ * @return NULL on error, pointer to dnbd3_signal_t on success.
*/
-int signal_newBlocking();
+dnbd3_signal_t* signal_newBlocking();
/**
* Trigger the given signal, so a wait or clear call will succeed.
* @return SIGNAL_OK on success, SIGNAL_ERROR on error
*/
-int signal_call(int signalFd);
+int signal_call(const dnbd3_signal_t* const signal);
/**
* Wait for given signal, with an optional timeout.
@@ -31,18 +33,25 @@ int signal_call(int signalFd);
* SIGNAL_TIMEOUT if the timeout was reached,
* SIGNAL_ERROR if some error occured
*/
-int signal_wait(int signalFd, int timeoutMs);
+int signal_wait(const dnbd3_signal_t* const signal, int timeoutMs);
/**
- * Clears any pending signals on this signal fd.
+ * Clears any pending signals on this signal.
* @return number of signals that were pending,
* SIGNAL_ERROR if some error occured
*/
-int signal_clear(int signalFd);
+int signal_clear(const dnbd3_signal_t* const signal);
/**
* Close the given signal.
*/
-void signal_close(int signalFd);
+void signal_close(const dnbd3_signal_t* const signal);
+
+/**
+ * Get a file descriptor for the given signal that can be
+ * waited on using poll or similar.
+ * @return -1 if the signal is invalid
+ */
+int signal_getWaitFd(const dnbd3_signal_t* const signal);
#endif