X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Fpipe.c;h=4fe45efada3e7dabfefd57b72b71cbcf167f2b03;hp=09e905de4fb64f1819a9cf5b3b8cdfc6281c015b;hb=b6151646d77a70cd8054543c07924c840646950b;hpb=6c1c0768320135c6936c371b09731851b508c023 diff --git a/src/common/pipe.c b/src/common/pipe.c index 09e905de4..4fe45efad 100644 --- a/src/common/pipe.c +++ b/src/common/pipe.c @@ -15,11 +15,12 @@ * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE #define _LGPL_SOURCE #include #include #include +#include +#include #include @@ -113,20 +114,88 @@ end: return ret_val; } +static struct lttng_pipe *_pipe_create(void) +{ + int ret; + struct lttng_pipe *p; + + p = zmalloc(sizeof(*p)); + if (!p) { + PERROR("zmalloc pipe create"); + goto end; + } + p->fd[0] = p->fd[1] = -1; + + ret = pthread_mutex_init(&p->read_mutex, NULL); + if (ret) { + PERROR("pthread_mutex_init read lock pipe create"); + goto error_destroy; + } + ret = pthread_mutex_init(&p->write_mutex, NULL); + if (ret) { + PERROR("pthread_mutex_init write lock pipe create"); + goto error_destroy_rmutex; + } +end: + return p; +error_destroy_rmutex: + (void) pthread_mutex_destroy(&p->read_mutex); +error_destroy: + free(p); + return NULL; +} + +static int _pipe_set_flags(struct lttng_pipe *pipe, int flags) +{ + int i, ret = 0; + + if (!flags) { + goto end; + } + + for (i = 0; i < 2; i++) { + if (flags & O_NONBLOCK) { + ret = fcntl(pipe->fd[i], F_SETFL, O_NONBLOCK); + if (ret < 0) { + PERROR("fcntl lttng pipe %d", flags); + goto end; + } + } + if (flags & FD_CLOEXEC) { + ret = fcntl(pipe->fd[i], F_SETFD, FD_CLOEXEC); + if (ret < 0) { + PERROR("fcntl lttng pipe %d", flags); + goto end; + } + } + /* + * We only check for O_NONBLOCK or FD_CLOEXEC, if another flag is + * needed, we can add it, but for now just make sure we don't make + * mistakes with the parameters we pass. + */ + if (!(flags & O_NONBLOCK) && !(flags & FD_CLOEXEC)) { + fprintf(stderr, "Unsupported flag\n"); + ret = -1; + goto end; + } + } +end: + return ret; +} /* * Open a new lttng pipe and set flags using fcntl(). * * Return a newly allocated lttng pipe on success or else NULL. */ +LTTNG_HIDDEN struct lttng_pipe *lttng_pipe_open(int flags) { int ret; struct lttng_pipe *p; - p = zmalloc(sizeof(*p)); + p = _pipe_create(); if (!p) { - PERROR("zmalloc pipe open"); goto error; } @@ -135,37 +204,79 @@ struct lttng_pipe *lttng_pipe_open(int flags) PERROR("lttng pipe"); goto error; } + p->r_state = LTTNG_PIPE_STATE_OPENED; + p->w_state = LTTNG_PIPE_STATE_OPENED; - if (flags) { - int i; - - for (i = 0; i < 2; i++) { - ret = fcntl(p->fd[i], F_SETFD, flags); - if (ret < 0) { - PERROR("fcntl lttng pipe %d", flags); - goto error; - } - } + ret = _pipe_set_flags(p, flags); + if (ret) { + goto error; } - pthread_mutex_init(&p->read_mutex, NULL); - pthread_mutex_init(&p->write_mutex, NULL); - p->r_state = LTTNG_PIPE_STATE_OPENED; - p->w_state = LTTNG_PIPE_STATE_OPENED; p->flags = flags; return p; - error: lttng_pipe_destroy(p); return NULL; } +/* + * Open a new lttng pipe at path and set flags using fcntl(). + * + * Return a newly allocated lttng pipe on success or else NULL. + */ +LTTNG_HIDDEN +struct lttng_pipe *lttng_pipe_named_open(const char *path, mode_t mode, + int flags) +{ + int ret, fd_r, fd_w; + struct lttng_pipe *pipe; + + pipe = _pipe_create(); + if (!pipe) { + goto error; + } + + ret = mkfifo(path, mode); + if (ret) { + PERROR("mkfifo"); + goto error; + } + + fd_r = open(path, O_RDONLY | O_NONBLOCK); + if (fd_r < 0) { + PERROR("open fifo"); + goto error; + } + pipe->fd[0] = fd_r; + pipe->r_state = LTTNG_PIPE_STATE_OPENED; + + fd_w = open(path, O_WRONLY | O_NONBLOCK); + if (fd_w < 0) { + PERROR("open fifo"); + goto error; + } + pipe->fd[1] = fd_w; + pipe->w_state = LTTNG_PIPE_STATE_OPENED; + + ret = _pipe_set_flags(pipe, flags); + if (ret) { + goto error; + } + pipe->flags = flags; + + return pipe; +error: + lttng_pipe_destroy(pipe); + return NULL; +} + /* * Close read side of a lttng pipe. * * Return 0 on success else a negative value. */ +LTTNG_HIDDEN int lttng_pipe_read_close(struct lttng_pipe *pipe) { int ret; @@ -185,6 +296,7 @@ int lttng_pipe_read_close(struct lttng_pipe *pipe) * * Return 0 on success else a negative value. */ +LTTNG_HIDDEN int lttng_pipe_write_close(struct lttng_pipe *pipe) { int ret; @@ -203,6 +315,7 @@ int lttng_pipe_write_close(struct lttng_pipe *pipe) * * Return 0 on success else a negative value. */ +LTTNG_HIDDEN int lttng_pipe_close(struct lttng_pipe *pipe) { int ret, ret_val = 0; @@ -225,6 +338,7 @@ int lttng_pipe_close(struct lttng_pipe *pipe) /* * Close and destroy a lttng pipe object. Finally, pipe is freed. */ +LTTNG_HIDDEN void lttng_pipe_destroy(struct lttng_pipe *pipe) { int ret; @@ -261,6 +375,7 @@ void lttng_pipe_destroy(struct lttng_pipe *pipe) * Return "count" on success. Return < count on error. errno can be used * to check the actual error. */ +LTTNG_HIDDEN ssize_t lttng_pipe_read(struct lttng_pipe *pipe, void *buf, size_t count) { ssize_t ret; @@ -286,6 +401,7 @@ error: * Return "count" on success. Return < count on error. errno can be used * to check the actual error. */ +LTTNG_HIDDEN ssize_t lttng_pipe_write(struct lttng_pipe *pipe, const void *buf, size_t count) { @@ -305,3 +421,69 @@ error: unlock_write_side(pipe); return ret; } + +/* + * Return and release the read end of the pipe. + * + * This call transfers the ownership of the read fd of the underlying pipe + * to the caller if it is still open. + * + * Returns the fd of the read end of the pipe, or -1 if it was already closed or + * released. + */ +LTTNG_HIDDEN +int lttng_pipe_release_readfd(struct lttng_pipe *pipe) +{ + int ret; + + if (!pipe) { + ret = -1; + goto end; + } + + lock_read_side(pipe); + if (!lttng_pipe_is_read_open(pipe)) { + ret = -1; + goto end_unlock; + } + ret = pipe->fd[0]; + pipe->fd[0] = -1; + pipe->r_state = LTTNG_PIPE_STATE_CLOSED; +end_unlock: + unlock_read_side(pipe); +end: + return ret; +} + +/* + * Return and release the write end of the pipe. + * + * This call transfers the ownership of the write fd of the underlying pipe + * to the caller if it is still open. + * + * Returns the fd of the write end of the pipe, or -1 if it was alwritey closed + * or released. + */ +LTTNG_HIDDEN +int lttng_pipe_release_writefd(struct lttng_pipe *pipe) +{ + int ret; + + if (!pipe) { + ret = -1; + goto end; + } + + lock_write_side(pipe); + if (!lttng_pipe_is_write_open(pipe)) { + ret = -1; + goto end_unlock; + } + ret = pipe->fd[1]; + pipe->fd[1] = -1; + pipe->w_state = LTTNG_PIPE_STATE_CLOSED; +end_unlock: + unlock_write_side(pipe); +end: + return ret; +}