2 * Copyright (C) 2017 - Julien Desfossez <jdesfossez@efficios.com>
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of the GNU General Public License, version 2 only, as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
13 * You should have received a copy of the GNU General Public License along with
14 * this program; if not, write to the Free Software Foundation, Inc., 51
15 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 #include "sessiond-timer.h"
24 #include "health-sessiond.h"
25 #include "rotation-thread.h"
28 struct timer_signal_data timer_signal
= {
31 .lock
= PTHREAD_MUTEX_INITIALIZER
,
35 * Set custom signal mask to current thread.
38 void setmask(sigset_t
*mask
)
42 ret
= sigemptyset(mask
);
44 PERROR("sigemptyset");
46 ret
= sigaddset(mask
, LTTNG_SESSIOND_SIG_TEARDOWN
);
48 PERROR("sigaddset teardown");
50 ret
= sigaddset(mask
, LTTNG_SESSIOND_SIG_EXIT
);
52 PERROR("sigaddset exit");
54 ret
= sigaddset(mask
, LTTNG_SESSIOND_SIG_ROTATE_PENDING
);
56 PERROR("sigaddset switch");
61 * This is the same function as consumer_timer_signal_thread_qs, when it
62 * returns, it means that no timer signr is currently pending or being handled
63 * by the timer thread. This cannot be called from the timer thread.
66 void sessiond_timer_signal_thread_qs(unsigned int signr
)
72 * We need to be the only thread interacting with the thread
73 * that manages signals for teardown synchronization.
75 pthread_mutex_lock(&timer_signal
.lock
);
77 /* Ensure we don't have any signal queued for this session. */
79 ret
= sigemptyset(&pending_set
);
81 PERROR("sigemptyset");
83 ret
= sigpending(&pending_set
);
87 if (!sigismember(&pending_set
, signr
)) {
94 * From this point, no new signal handler will be fired that would try to
95 * access "session". However, we still need to wait for any currently
96 * executing handler to complete.
99 CMM_STORE_SHARED(timer_signal
.qs_done
, 0);
103 * Kill with LTTNG_SESSIOND_SIG_TEARDOWN, so signal management thread
106 kill(getpid(), LTTNG_SESSIOND_SIG_TEARDOWN
);
108 while (!CMM_LOAD_SHARED(timer_signal
.qs_done
)) {
113 pthread_mutex_unlock(&timer_signal
.lock
);
117 * Start a timer on a session that will fire at a given interval
118 * (timer_interval_us) and fire a given signal (signal).
120 * Returns a negative value on error, 0 if a timer was created, and
121 * a positive value if no timer was created (not an error).
124 int session_timer_start(timer_t
*timer_id
, struct ltt_session
*session
,
125 unsigned int timer_interval_us
, int signal
, bool one_shot
)
127 int ret
= 0, delete_ret
;
129 struct itimerspec its
;
133 sev
.sigev_notify
= SIGEV_SIGNAL
;
134 sev
.sigev_signo
= signal
;
135 sev
.sigev_value
.sival_ptr
= session
;
136 ret
= timer_create(CLOCKID
, &sev
, timer_id
);
138 PERROR("timer_create");
142 its
.it_value
.tv_sec
= timer_interval_us
/ 1000000;
143 its
.it_value
.tv_nsec
= (timer_interval_us
% 1000000) * 1000;
145 its
.it_interval
.tv_sec
= 0;
146 its
.it_interval
.tv_nsec
= 0;
148 its
.it_interval
.tv_sec
= its
.it_value
.tv_sec
;
149 its
.it_interval
.tv_nsec
= its
.it_value
.tv_nsec
;
152 ret
= timer_settime(*timer_id
, 0, &its
, NULL
);
154 PERROR("timer_settime");
155 goto error_destroy_timer
;
160 delete_ret
= timer_delete(*timer_id
);
161 if (delete_ret
== -1) {
162 PERROR("timer_delete");
170 int session_timer_stop(timer_t
*timer_id
, int signal
)
174 ret
= timer_delete(*timer_id
);
176 PERROR("timer_delete");
180 sessiond_timer_signal_thread_qs(signal
);
186 int sessiond_timer_rotate_pending_start(struct ltt_session
*session
,
187 unsigned int interval_us
)
191 DBG("Enabling rotate pending timer on session %" PRIu64
, session
->id
);
193 * We arm this timer in a one-shot mode so we don't have to disable it
194 * explicitly (which could deadlock if the timer thread is blocked writing
195 * in the rotation_timer_pipe).
196 * Instead, we re-arm it if needed after the rotation_pending check as
197 * returned. Also, this timer is usually only needed once, so there is no
198 * need to go through the whole signal teardown scheme everytime.
200 ret
= session_timer_start(&session
->rotate_relay_pending_timer
,
201 session
, interval_us
,
202 LTTNG_SESSIOND_SIG_ROTATE_PENDING
,
203 /* one-shot */ true);
205 session
->rotate_relay_pending_timer_enabled
= true;
212 * Stop and delete the channel's live timer.
213 * Called with session and session_list locks held.
215 void sessiond_timer_rotate_pending_stop(struct ltt_session
*session
)
221 DBG("Disabling timer rotate pending on session %" PRIu64
, session
->id
);
222 ret
= session_timer_stop(&session
->rotate_relay_pending_timer
,
223 LTTNG_SESSIOND_SIG_ROTATE_PENDING
);
225 ERR("Failed to stop rotate_pending timer");
228 session
->rotate_relay_pending_timer_enabled
= false;
232 * Block the RT signals for the entire process. It must be called from the
233 * sessiond main before creating the threads
235 int sessiond_timer_signal_init(void)
240 /* Block signal for entire process, so only our thread processes it. */
242 ret
= pthread_sigmask(SIG_BLOCK
, &mask
, NULL
);
245 PERROR("pthread_sigmask");
252 * Called with the rotation_timer_queue lock held.
253 * Return true if the same timer job already exists in the queue, false if not.
256 bool check_duplicate_timer_job(struct timer_thread_parameters
*ctx
,
257 struct ltt_session
*session
, unsigned int signal
)
260 struct sessiond_rotation_timer
*node
;
263 cds_list_for_each_entry(node
, &ctx
->rotation_timer_queue
->list
, head
) {
264 if (node
->session_id
== session
->id
&& node
->signal
== signal
) {
276 * Add the session ID and signal value to the rotation_timer_queue if it is
277 * not already there and wakeup the rotation thread. The rotation thread
278 * empties the whole queue everytime it is woken up. The event_pipe is
279 * non-blocking, if it would block, we just return because we know the
280 * rotation thread will be awaken anyway.
283 int enqueue_timer_rotate_job(struct timer_thread_parameters
*ctx
,
284 struct ltt_session
*session
, unsigned int signal
)
287 bool has_duplicate_timer_job
;
290 pthread_mutex_lock(&ctx
->rotation_timer_queue
->lock
);
291 has_duplicate_timer_job
= check_duplicate_timer_job(ctx
, session
,
294 if (!has_duplicate_timer_job
) {
295 struct sessiond_rotation_timer
*timer_data
= NULL
;
297 timer_data
= zmalloc(sizeof(struct sessiond_rotation_timer
));
299 PERROR("Allocation of timer data");
302 timer_data
->session_id
= session
->id
;
303 timer_data
->signal
= signal
;
304 cds_list_add_tail(&timer_data
->head
,
305 &ctx
->rotation_timer_queue
->list
);
308 * This timer job is already pending, we don't need to add
311 pthread_mutex_unlock(&ctx
->rotation_timer_queue
->lock
);
315 pthread_mutex_unlock(&ctx
->rotation_timer_queue
->lock
);
318 lttng_pipe_get_writefd(ctx
->rotation_timer_queue
->event_pipe
),
322 * We do not want to block in the timer handler, the job has been
323 * enqueued in the list, the wakeup pipe is probably full, the job
324 * will be processed when the rotation_thread catches up.
326 if (errno
== EAGAIN
|| errno
== EWOULDBLOCK
) {
330 PERROR("Timer wakeup rotation thread");
344 * Ask the rotation thread to check if the last rotation started in this
345 * session is still pending on the relay.
348 void relay_rotation_pending_timer(struct timer_thread_parameters
*ctx
,
349 int sig
, siginfo_t
*si
)
352 struct ltt_session
*session
= si
->si_value
.sival_ptr
;
355 ret
= enqueue_timer_rotate_job(ctx
, session
, LTTNG_SESSIOND_SIG_ROTATE_PENDING
);
357 PERROR("wakeup rotate pipe");
362 * This thread is the sighandler for the timer signals.
364 void *sessiond_timer_thread(void *data
)
369 struct timer_thread_parameters
*ctx
= data
;
371 rcu_register_thread();
374 health_register(health_sessiond
, HEALTH_SESSIOND_TYPE_TIMER
);
376 health_code_update();
378 /* Only self thread will receive signal mask. */
380 CMM_STORE_SHARED(timer_signal
.tid
, pthread_self());
383 health_code_update();
386 signr
= sigwaitinfo(&mask
, &info
);
390 * NOTE: cascading conditions are used instead of a switch case
391 * since the use of SIGRTMIN in the definition of the signals'
392 * values prevents the reduction to an integer constant.
395 if (errno
!= EINTR
) {
396 PERROR("sigwaitinfo");
399 } else if (signr
== LTTNG_SESSIOND_SIG_TEARDOWN
) {
401 CMM_STORE_SHARED(timer_signal
.qs_done
, 1);
403 DBG("Signal timer metadata thread teardown");
404 } else if (signr
== LTTNG_SESSIOND_SIG_EXIT
) {
406 } else if (signr
== LTTNG_SESSIOND_SIG_ROTATE_PENDING
) {
407 relay_rotation_pending_timer(ctx
, info
.si_signo
, &info
);
409 ERR("Unexpected signal %d\n", info
.si_signo
);
414 DBG("[timer-thread] Exit");
415 health_unregister(health_sessiond
);
416 rcu_thread_offline();
417 rcu_unregister_thread();