Code

plugin: Make sdb_plugin_info_t public.
[sysdb.git] / src / utils / channel.c
index 22e31a8b4eb0303e063ca6b3bfae2e0e8dcb19ad..7c5c002ae545f43901e5b9dab352329936218b67 100644 (file)
  * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#if HAVE_CONFIG_H
+#      include "config.h"
+#endif /* HAVE_CONFIG_H */
+
 #include "utils/channel.h"
 
 #include <assert.h>
 
+#include <errno.h>
+
 #include <stdlib.h>
 #include <string.h>
 
+#include <time.h>
+
 #include <pthread.h>
 
 /*
@@ -53,6 +61,8 @@ struct sdb_channel {
        size_t head;
        size_t tail;
        _Bool full;
+
+       _Bool shutdown;
 };
 
 /*
@@ -75,7 +85,7 @@ channel_write(sdb_channel_t *chan, const void *data)
 {
        assert(chan);
 
-       if (chan->full)
+       if (chan->full || chan->shutdown)
                return -1;
        else if (! data)
                return 0;
@@ -167,11 +177,15 @@ sdb_channel_select(sdb_channel_t *chan, int *wantread, void *read_data,
 {
        int status = 0;
 
-       if (! chan)
+       if (! chan) {
+               errno = EINVAL;
                return -1;
+       }
 
-       if ((! wantread) && (! read_data) && (! wantwrite) && (! write_data))
+       if ((! wantread) && (! read_data) && (! wantwrite) && (! write_data)) {
+               errno = EINVAL;
                return -1;
+       }
 
        pthread_mutex_lock(&chan->lock);
        while (! status) {
@@ -191,15 +205,41 @@ sdb_channel_select(sdb_channel_t *chan, int *wantread, void *read_data,
                                break;
                }
 
-               if (timeout)
+               if (chan->shutdown) {
+                       if (read_status)
+                               status = EBADF;
+                       break;
+               }
+
+               if (timeout) {
+                       struct timespec abstime;
+
+                       if (clock_gettime(CLOCK_REALTIME, &abstime)) {
+                               pthread_mutex_unlock(&chan->lock);
+                               return -1;
+                       }
+
+                       abstime.tv_sec += timeout->tv_sec;
+                       abstime.tv_nsec += timeout->tv_nsec;
+
+                       if (abstime.tv_nsec > 1000000000) {
+                               abstime.tv_nsec -= 1000000000;
+                               abstime.tv_sec += 1;
+                       }
+
                        status = pthread_cond_timedwait(&chan->cond, &chan->lock,
-                                       timeout);
+                                       &abstime);
+               }
                else
                        status = pthread_cond_wait(&chan->cond, &chan->lock);
        }
-
        pthread_mutex_unlock(&chan->lock);
-       return status;
+
+       if (status) {
+               errno = status;
+               return -1;
+       }
+       return 0;
 } /* sdb_channel_select */
 
 int
@@ -230,5 +270,14 @@ sdb_channel_read(sdb_channel_t *chan, void *data)
        return status;
 } /* sdb_channel_read */
 
+int
+sdb_channel_shutdown(sdb_channel_t *chan)
+{
+       if (! chan)
+               return -1;
+       chan->shutdown = 1;
+       return 0;
+} /* sdb_channel_shutdown */
+
 /* vim: set tw=78 sw=4 ts=4 noexpandtab : */