Fix: statements with side-effects in assert statements
[deliverable/lttng-tools.git] / src / bin / lttng-sessiond / thread-utils.c
CommitLineData
a7333da7 1/*
ab5be9fa
MJ
2 * Copyright (C) 2011 David Goulet <david.goulet@polymtl.ca>
3 * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
4 * Copyright (C) 2013 Jérémie Galarneau <jeremie.galarneau@efficios.com>
a7333da7 5 *
ab5be9fa 6 * SPDX-License-Identifier: GPL-2.0-only
a7333da7 7 *
a7333da7
JG
8 */
9
10#include "lttng-sessiond.h"
11#include "utils.h"
12#include <common/utils.h>
99d688f2
JG
13#include <pthread.h>
14
a7333da7
JG
15/*
16 * Quit pipe for all threads. This permits a single cancellation point
17 * for all threads when receiving an event on the pipe.
18 */
19static int thread_quit_pipe[2] = { -1, -1 };
20
21/*
22 * Init thread quit pipe.
23 *
24 * Return -1 on error or 0 if all pipes are created.
25 */
26static int __init_thread_quit_pipe(int *a_pipe)
27{
28 int ret, i;
29
30 ret = pipe(a_pipe);
31 if (ret < 0) {
32 PERROR("thread quit pipe");
33 goto error;
34 }
35
36 for (i = 0; i < 2; i++) {
37 ret = fcntl(a_pipe[i], F_SETFD, FD_CLOEXEC);
38 if (ret < 0) {
39 PERROR("fcntl");
40 goto error;
41 }
42 }
43
44error:
45 return ret;
46}
47
48int sessiond_init_thread_quit_pipe(void)
49{
50 return __init_thread_quit_pipe(thread_quit_pipe);
51}
52
53int sessiond_check_thread_quit_pipe(int fd, uint32_t events)
54{
55 return (fd == thread_quit_pipe[0] && (events & LPOLLIN));
56}
57
58/*
59 * Wait for a notification on the quit pipe (with a timeout).
60 *
99d688f2
JG
61 * A timeout value of -1U means no timeout.
62 *
a7333da7
JG
63 * Returns 1 if the caller should quit, 0 if the timeout was reached, and
64 * -1 if an error was encountered.
65 */
2d54bfb6 66int sessiond_wait_for_quit_pipe(int timeout_ms)
a7333da7
JG
67{
68 int ret;
2d54bfb6 69 struct lttng_poll_event events;
a7333da7 70
2d54bfb6
MD
71 ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
72 if (ret < 0) {
73 PERROR("Failed to initialize poll/epoll set");
74 ret = -1;
75 goto end;
76 }
77 ret = lttng_poll_add(&events, thread_quit_pipe[0], LPOLLIN | LPOLLERR);
78 if (ret < 0) {
79 PERROR("Failed to add file descriptor to poll/epoll set");
80 ret = -1;
81 goto end_clean_poll;
82 }
83 ret = lttng_poll_wait(&events, timeout_ms);
a7333da7
JG
84 if (ret > 0) {
85 /* Should quit. */
86 ret = 1;
87 } else if (ret < 0 && errno != EINTR) {
88 /* Unknown error. */
2d54bfb6 89 PERROR("Failed to epoll()/poll() thread quit pipe");
a7333da7
JG
90 ret = -1;
91 } else {
92 /* Timeout reached. */
93 ret = 0;
94 }
2d54bfb6
MD
95end_clean_poll:
96 lttng_poll_clean(&events);
97end:
a7333da7
JG
98 return ret;
99}
100
101int sessiond_notify_quit_pipe(void)
102{
103 return notify_thread_pipe(thread_quit_pipe[1]);
104}
105
106void sessiond_close_quit_pipe(void)
107{
108 utils_close_pipe(thread_quit_pipe);
109}
110
111static
112int __sessiond_set_thread_pollset(struct lttng_poll_event *events, size_t size,
113 int *a_pipe)
114{
115 int ret;
116
117 assert(events);
118
119 ret = lttng_poll_create(events, size, LTTNG_CLOEXEC);
120 if (ret < 0) {
121 goto error;
122 }
123
124 /* Add quit pipe */
125 ret = lttng_poll_add(events, a_pipe[0], LPOLLIN | LPOLLERR);
126 if (ret < 0) {
127 goto error;
128 }
129
130 return 0;
131
132error:
133 return ret;
134}
135
136/*
137 * Create a poll set with O_CLOEXEC and add the thread quit pipe to the set.
138 */
139int sessiond_set_thread_pollset(struct lttng_poll_event *events, size_t size)
140{
141 return __sessiond_set_thread_pollset(events, size, thread_quit_pipe);
142}
This page took 0.058432 seconds and 5 git commands to generate.