/* $Id: thread.c,v 1.1 2002/02/05 22:49:02 poettering Exp $ * * This file is part of libshbuf. * * asd is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free * Software Foundation; either version 2 of the License, or (at your * option) any later version. * * asd is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * for more details. * * You should have received a copy of the GNU General Public License * along with libshbuf; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. */ #include #include #include #include #include #include #include #include "shbuf.h" #include "internal.h" #include "nonblock.h" #include "shbuferr.h" static void* _notify_thread(void *p) { int msgtype; shbuf *sb = (shbuf*) p; assert(sb); sb->thread = pthread_self(); siginterrupt(SIGPIPE, 0); siginterrupt(SIGINT, 0); siginterrupt(SIGTERM, 0); siginterrupt(SIGHUP, 0); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, NULL); msgtype = sb->is_provider ? 1 : 2; for (;;) { struct { long mtype; char mtext[1]; } msgbuf; if (msgrcv(sb->msgid, &msgbuf, 1, msgtype, MSG_NOERROR) < 0) { if (errno == EINTR) continue; break; } if (write(sb->fifo_fd_write, &msgbuf.mtext[0], 1) != 1) if (errno != EAGAIN && errno != EINTR) break; } sb->is_dead = 1; return NULL; } int thread_start(shbuf *sb) { int f[2]; assert(sb); if (sb->thread != (pthread_t) 0) return 0; if (pipe(f) != 0) { shbuf_set_errno(SHBUF_COULDNOTCREATEPIPE); return -1; } sb->fifo_fd_read = f[0]; sb->fifo_fd_write = f[1]; set_nonblocking(sb->fifo_fd_write, 1); set_nonblocking(sb->fifo_fd_read, 1); if (pthread_create(&sb->thread, NULL, _notify_thread, sb) == 0) return 0; close(sb->fifo_fd_read); close(sb->fifo_fd_write); sb->fifo_fd_read = sb->fifo_fd_write = -1; shbuf_set_errno(SHBUF_COULDNOTCREATETHREAD); return -1; } void thread_stop(shbuf *sb) { assert(sb); if (sb->thread == (pthread_t) 0) return; pthread_cancel(sb->thread); pthread_join(sb->thread, NULL); sb->thread = (pthread_t) 0; close(sb->fifo_fd_read); close(sb->fifo_fd_write); sb->fifo_fd_read = sb->fifo_fd_write = -1; }