X-Git-Url: https://git.lttng.org/?p=lttng-tools.git;a=blobdiff_plain;f=src%2Fcommon%2Fpipe.c;h=868c1f3de839dd71847604062ed063b0acb31b1d;hp=2544f7b45f76265a8d757d540686953047092758;hb=7ca172c15891d4ff3f711dcc05f991fd2c094bc7;hpb=a247c6e01e8840f757c5806dfcd2c7dd548bbaa2 diff --git a/src/common/pipe.c b/src/common/pipe.c index 2544f7b45..868c1f3de 100644 --- a/src/common/pipe.c +++ b/src/common/pipe.c @@ -1,25 +1,16 @@ /* - * Copyright (C) 2013 - David Goulet + * Copyright (C) 2013 David Goulet * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License, version 2 only, as - * published by the Free Software Foundation. + * SPDX-License-Identifier: GPL-2.0-only * - * This program 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 - * this program; if not, write to the Free Software Foundation, Inc., 51 - * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ -#define _GNU_SOURCE #define _LGPL_SOURCE #include #include #include +#include +#include #include @@ -113,6 +104,74 @@ 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(). @@ -125,9 +184,8 @@ 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; } @@ -136,32 +194,73 @@ 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. * @@ -312,3 +411,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; +}