Cleanup: remove ignored flags from poll events bitmasks
[lttng-tools.git] / src / lib / lttng-ctl / channel.cpp
CommitLineData
a58c490f 1/*
ab5be9fa 2 * Copyright (C) 2017 Jérémie Galarneau <jeremie.galarneau@efficios.com>
a58c490f 3 *
ab5be9fa 4 * SPDX-License-Identifier: LGPL-2.1-only
a58c490f 5 *
a58c490f
JG
6 */
7
c9e313bc
SM
8#include <lttng/notification/notification-internal.hpp>
9#include <lttng/notification/channel-internal.hpp>
10#include <lttng/condition/condition-internal.hpp>
a58c490f 11#include <lttng/endpoint.h>
c9e313bc
SM
12#include <common/defaults.hpp>
13#include <common/error.hpp>
14#include <common/dynamic-buffer.hpp>
15#include <common/utils.hpp>
16#include <common/defaults.hpp>
17#include <common/payload.hpp>
18#include <common/payload-view.hpp>
19#include <common/unix.hpp>
20#include "lttng-ctl-helper.hpp"
21#include <common/compat/poll.hpp>
a58c490f
JG
22
23static
24int handshake(struct lttng_notification_channel *channel);
25
26/*
27 * Populates the reception buffer with the next complete message.
1d757b1c 28 * The caller must acquire the channel's lock.
a58c490f
JG
29 */
30static
31int receive_message(struct lttng_notification_channel *channel)
32{
33 ssize_t ret;
34 struct lttng_notification_channel_message msg;
35
882093ee 36 lttng_payload_clear(&channel->reception_payload);
a58c490f
JG
37
38 ret = lttcomm_recv_unix_sock(channel->socket, &msg, sizeof(msg));
39 if (ret <= 0) {
40 ret = -1;
41 goto error;
42 }
43
44 if (msg.size > DEFAULT_MAX_NOTIFICATION_CLIENT_MESSAGE_PAYLOAD_SIZE) {
45 ret = -1;
46 goto error;
47 }
48
49 /* Add message header at buffer's start. */
882093ee 50 ret = lttng_dynamic_buffer_append(&channel->reception_payload.buffer, &msg,
a58c490f
JG
51 sizeof(msg));
52 if (ret) {
53 goto error;
54 }
55
63ae8472
JR
56 if (msg.size == 0) {
57 goto skip_payload;
58 }
59
a58c490f 60 /* Reserve space for the payload. */
882093ee
JR
61 ret = lttng_dynamic_buffer_set_size(&channel->reception_payload.buffer,
62 channel->reception_payload.buffer.size + msg.size);
a58c490f
JG
63 if (ret) {
64 goto error;
65 }
66
67 /* Receive message payload. */
68 ret = lttcomm_recv_unix_sock(channel->socket,
882093ee 69 channel->reception_payload.buffer.data + sizeof(msg), msg.size);
a58c490f
JG
70 if (ret < (ssize_t) msg.size) {
71 ret = -1;
72 goto error;
73 }
882093ee 74
63ae8472 75skip_payload:
882093ee
JR
76 /* Receive message fds. */
77 if (msg.fds != 0) {
78 ret = lttcomm_recv_payload_fds_unix_sock(channel->socket,
79 msg.fds, &channel->reception_payload);
80 if (ret < sizeof(int) * msg.fds) {
81 ret = -1;
82 goto error;
83 }
84 }
a58c490f
JG
85 ret = 0;
86end:
87 return ret;
88error:
882093ee 89 lttng_payload_clear(&channel->reception_payload);
a58c490f
JG
90 goto end;
91}
92
93static
94enum lttng_notification_channel_message_type get_current_message_type(
95 struct lttng_notification_channel *channel)
96{
97 struct lttng_notification_channel_message *msg;
98
a0377dfe 99 LTTNG_ASSERT(channel->reception_payload.buffer.size >= sizeof(*msg));
a58c490f
JG
100
101 msg = (struct lttng_notification_channel_message *)
882093ee 102 channel->reception_payload.buffer.data;
a58c490f
JG
103 return (enum lttng_notification_channel_message_type) msg->type;
104}
105
106static
107struct lttng_notification *create_notification_from_current_message(
108 struct lttng_notification_channel *channel)
109{
110 ssize_t ret;
111 struct lttng_notification *notification = NULL;
a58c490f 112
882093ee 113 if (channel->reception_payload.buffer.size <=
a58c490f
JG
114 sizeof(struct lttng_notification_channel_message)) {
115 goto end;
116 }
117
c0a66c84 118 {
882093ee
JR
119 struct lttng_payload_view view = lttng_payload_view_from_payload(
120 &channel->reception_payload,
c0a66c84
JG
121 sizeof(struct lttng_notification_channel_message),
122 -1);
123
124 ret = lttng_notification_create_from_payload(
125 &view, &notification);
126 }
a58c490f 127
882093ee 128 if (ret != channel->reception_payload.buffer.size -
a58c490f
JG
129 sizeof(struct lttng_notification_channel_message)) {
130 lttng_notification_destroy(notification);
131 notification = NULL;
132 goto end;
133 }
134end:
135 return notification;
136}
137
138struct lttng_notification_channel *lttng_notification_channel_create(
139 struct lttng_endpoint *endpoint)
140{
141 int fd, ret;
142 bool is_in_tracing_group = false, is_root = false;
143 char *sock_path = NULL;
144 struct lttng_notification_channel *channel = NULL;
145
146 if (!endpoint ||
147 endpoint != lttng_session_daemon_notification_endpoint) {
148 goto end;
149 }
150
64803277 151 sock_path = calloc<char>(LTTNG_PATH_MAX);
a58c490f
JG
152 if (!sock_path) {
153 goto end;
154 }
155
64803277 156 channel = zmalloc<lttng_notification_channel>();
a58c490f
JG
157 if (!channel) {
158 goto end;
159 }
160 channel->socket = -1;
161 pthread_mutex_init(&channel->lock, NULL);
882093ee 162 lttng_payload_init(&channel->reception_payload);
a58c490f
JG
163 CDS_INIT_LIST_HEAD(&channel->pending_notifications.list);
164
165 is_root = (getuid() == 0);
166 if (!is_root) {
167 is_in_tracing_group = lttng_check_tracing_group();
168 }
169
170 if (is_root || is_in_tracing_group) {
e1b624d0 171 ret = lttng_strncpy(sock_path,
a58c490f
JG
172 DEFAULT_GLOBAL_NOTIFICATION_CHANNEL_UNIX_SOCK,
173 LTTNG_PATH_MAX);
e1b624d0
JG
174 if (ret) {
175 ret = -LTTNG_ERR_INVALID;
176 goto error;
177 }
178
a58c490f
JG
179 ret = lttcomm_connect_unix_sock(sock_path);
180 if (ret >= 0) {
181 fd = ret;
182 goto set_fd;
183 }
184 }
185
186 /* Fallback to local session daemon. */
187 ret = snprintf(sock_path, LTTNG_PATH_MAX,
188 DEFAULT_HOME_NOTIFICATION_CHANNEL_UNIX_SOCK,
189 utils_get_home_dir());
190 if (ret < 0 || ret >= LTTNG_PATH_MAX) {
191 goto error;
192 }
193
194 ret = lttcomm_connect_unix_sock(sock_path);
195 if (ret < 0) {
196 goto error;
197 }
198 fd = ret;
199
200set_fd:
201 channel->socket = fd;
202
203 ret = handshake(channel);
204 if (ret) {
205 goto error;
206 }
207end:
208 free(sock_path);
209 return channel;
210error:
211 lttng_notification_channel_destroy(channel);
212 channel = NULL;
213 goto end;
214}
215
216enum lttng_notification_channel_status
217lttng_notification_channel_get_next_notification(
218 struct lttng_notification_channel *channel,
219 struct lttng_notification **_notification)
220{
221 int ret;
222 struct lttng_notification *notification = NULL;
223 enum lttng_notification_channel_status status =
224 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
d977a743 225 struct lttng_poll_event events;
a58c490f
JG
226
227 if (!channel || !_notification) {
228 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
229 goto end;
230 }
231
94a61469
JG
232 pthread_mutex_lock(&channel->lock);
233
a58c490f
JG
234 if (channel->pending_notifications.count) {
235 struct pending_notification *pending_notification;
236
a0377dfe 237 LTTNG_ASSERT(!cds_list_empty(&channel->pending_notifications.list));
a58c490f
JG
238
239 /* Deliver one of the pending notifications. */
240 pending_notification = cds_list_first_entry(
241 &channel->pending_notifications.list,
242 struct pending_notification,
243 node);
244 notification = pending_notification->notification;
245 if (!notification) {
246 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED;
247 }
248 cds_list_del(&pending_notification->node);
249 channel->pending_notifications.count--;
250 free(pending_notification);
94a61469 251 goto end_unlock;
f83bcd90
JG
252 }
253
254 /*
d977a743
MD
255 * Block on interruptible epoll/poll() instead of the message reception
256 * itself as the recvmsg() wrappers always restart on EINTR. We choose
257 * to wait using interruptible epoll/poll() in order to:
f83bcd90
JG
258 * 1) Return if a signal occurs,
259 * 2) Not deal with partially received messages.
260 *
261 * The drawback to this approach is that we assume that messages
262 * are complete/well formed. If a message is shorter than its
263 * announced length, receive_message() will block on recvmsg()
264 * and never return (even if a signal is received).
265 */
d977a743
MD
266 ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
267 if (ret < 0) {
268 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
269 goto end_unlock;
270 }
1524f98c 271 ret = lttng_poll_add(&events, channel->socket, LPOLLIN);
d977a743
MD
272 if (ret < 0) {
273 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
274 goto end_clean_poll;
275 }
276 ret = lttng_poll_wait_interruptible(&events, -1);
277 if (ret <= 0) {
278 status = (ret == -1 && errno == EINTR) ?
f83bcd90
JG
279 LTTNG_NOTIFICATION_CHANNEL_STATUS_INTERRUPTED :
280 LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
d977a743 281 goto end_clean_poll;
a58c490f
JG
282 }
283
a58c490f
JG
284 ret = receive_message(channel);
285 if (ret) {
286 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
d977a743 287 goto end_clean_poll;
a58c490f
JG
288 }
289
290 switch (get_current_message_type(channel)) {
291 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
292 notification = create_notification_from_current_message(
293 channel);
294 if (!notification) {
295 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
d977a743 296 goto end_clean_poll;
a58c490f
JG
297 }
298 break;
299 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
300 /* No payload to consume. */
301 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_NOTIFICATIONS_DROPPED;
302 break;
303 default:
304 /* Protocol error. */
305 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
d977a743 306 goto end_clean_poll;
a58c490f
JG
307 }
308
d977a743
MD
309end_clean_poll:
310 lttng_poll_clean(&events);
a58c490f
JG
311end_unlock:
312 pthread_mutex_unlock(&channel->lock);
a57a7f22 313 *_notification = notification;
a58c490f 314end:
a58c490f
JG
315 return status;
316}
317
318static
319int enqueue_dropped_notification(
320 struct lttng_notification_channel *channel)
321{
322 int ret = 0;
323 struct pending_notification *pending_notification;
324 struct cds_list_head *last_element =
325 channel->pending_notifications.list.prev;
326
327 pending_notification = caa_container_of(last_element,
328 struct pending_notification, node);
329 if (!pending_notification->notification) {
330 /*
331 * The last enqueued notification indicates dropped
332 * notifications; there is nothing to do as we group
333 * dropped notifications together.
334 */
335 goto end;
336 }
337
338 if (channel->pending_notifications.count >=
339 DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT &&
340 pending_notification->notification) {
341 /*
342 * Discard the last enqueued notification to indicate
343 * that notifications were dropped at this point.
344 */
345 lttng_notification_destroy(
346 pending_notification->notification);
347 pending_notification->notification = NULL;
348 goto end;
349 }
350
64803277 351 pending_notification = zmalloc<struct pending_notification>();
a58c490f
JG
352 if (!pending_notification) {
353 ret = -1;
354 goto end;
355 }
356 CDS_INIT_LIST_HEAD(&pending_notification->node);
357 cds_list_add(&pending_notification->node,
358 &channel->pending_notifications.list);
359 channel->pending_notifications.count++;
360end:
361 return ret;
362}
363
364static
365int enqueue_notification_from_current_message(
366 struct lttng_notification_channel *channel)
367{
368 int ret = 0;
369 struct lttng_notification *notification;
370 struct pending_notification *pending_notification;
371
372 if (channel->pending_notifications.count >=
373 DEFAULT_CLIENT_MAX_QUEUED_NOTIFICATIONS_COUNT) {
374 /* Drop the notification. */
375 ret = enqueue_dropped_notification(channel);
376 goto end;
377 }
378
64803277 379 pending_notification = zmalloc<struct pending_notification>();
a58c490f
JG
380 if (!pending_notification) {
381 ret = -1;
382 goto error;
383 }
384 CDS_INIT_LIST_HEAD(&pending_notification->node);
385
386 notification = create_notification_from_current_message(channel);
387 if (!notification) {
388 ret = -1;
389 goto error;
390 }
391
392 pending_notification->notification = notification;
393 cds_list_add(&pending_notification->node,
394 &channel->pending_notifications.list);
395 channel->pending_notifications.count++;
396end:
397 return ret;
398error:
399 free(pending_notification);
400 goto end;
401}
402
1d757b1c
JG
403enum lttng_notification_channel_status
404lttng_notification_channel_has_pending_notification(
405 struct lttng_notification_channel *channel,
406 bool *_notification_pending)
407{
408 int ret;
409 enum lttng_notification_channel_status status =
410 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
d977a743 411 struct lttng_poll_event events;
1d757b1c
JG
412
413 if (!channel || !_notification_pending) {
414 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
415 goto end;
416 }
417
418 pthread_mutex_lock(&channel->lock);
419
420 if (channel->pending_notifications.count) {
421 *_notification_pending = true;
422 goto end_unlock;
423 }
424
425 if (channel->socket < 0) {
426 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_CLOSED;
427 goto end_unlock;
428 }
429
430 /*
431 * Check, without blocking, if data is available on the channel's
432 * socket. If there is data available, it is safe to read (blocking)
433 * on the socket for a message from the session daemon.
434 *
435 * Since all commands wait for the session daemon's reply before
436 * releasing the channel's lock, the protocol only allows for
437 * notifications and "notification dropped" messages to come
438 * through. If we receive a different message type, it is
439 * considered a protocol error.
440 *
441 * Note that this function is not guaranteed not to block. This
442 * will block until our peer (the session daemon) has sent a complete
443 * message if we see data available on the socket. If the peer does
444 * not respect the protocol, this may block indefinitely.
445 */
d977a743
MD
446 ret = lttng_poll_create(&events, 1, LTTNG_CLOEXEC);
447 if (ret < 0) {
448 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
449 goto end_unlock;
450 }
1524f98c 451 ret = lttng_poll_add(&events, channel->socket, LPOLLIN);
d977a743
MD
452 if (ret < 0) {
453 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
454 goto end_clean_poll;
455 }
456 /* timeout = 0: return immediately. */
457 ret = lttng_poll_wait_interruptible(&events, 0);
1d757b1c
JG
458 if (ret == 0) {
459 /* No data available. */
460 *_notification_pending = false;
d977a743 461 goto end_clean_poll;
1d757b1c
JG
462 } else if (ret < 0) {
463 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
d977a743 464 goto end_clean_poll;
1d757b1c
JG
465 }
466
467 /* Data available on socket. */
468 ret = receive_message(channel);
469 if (ret) {
470 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
d977a743 471 goto end_clean_poll;
1d757b1c
JG
472 }
473
474 switch (get_current_message_type(channel)) {
475 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
476 ret = enqueue_notification_from_current_message(channel);
477 if (ret) {
d977a743 478 goto end_clean_poll;
1d757b1c
JG
479 }
480 *_notification_pending = true;
481 break;
482 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
483 ret = enqueue_dropped_notification(channel);
484 if (ret) {
d977a743 485 goto end_clean_poll;
1d757b1c
JG
486 }
487 *_notification_pending = true;
488 break;
489 default:
490 /* Protocol error. */
491 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
d977a743 492 goto end_clean_poll;
1d757b1c
JG
493 }
494
d977a743
MD
495end_clean_poll:
496 lttng_poll_clean(&events);
1d757b1c
JG
497end_unlock:
498 pthread_mutex_unlock(&channel->lock);
499end:
500 return status;
501}
502
a58c490f
JG
503static
504int receive_command_reply(struct lttng_notification_channel *channel,
505 enum lttng_notification_channel_status *status)
506{
507 int ret;
508 struct lttng_notification_channel_command_reply *reply;
509
510 while (true) {
511 enum lttng_notification_channel_message_type msg_type;
512
513 ret = receive_message(channel);
514 if (ret) {
515 goto end;
516 }
517
518 msg_type = get_current_message_type(channel);
519 switch (msg_type) {
520 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_COMMAND_REPLY:
521 goto exit_loop;
522 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION:
523 ret = enqueue_notification_from_current_message(
524 channel);
525 if (ret) {
526 goto end;
527 }
528 break;
529 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_NOTIFICATION_DROPPED:
530 ret = enqueue_dropped_notification(channel);
531 if (ret) {
532 goto end;
533 }
534 break;
535 case LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE:
536 {
537 struct lttng_notification_channel_command_handshake *handshake;
538
539 handshake = (struct lttng_notification_channel_command_handshake *)
882093ee 540 (channel->reception_payload.buffer.data +
a58c490f
JG
541 sizeof(struct lttng_notification_channel_message));
542 channel->version.major = handshake->major;
543 channel->version.minor = handshake->minor;
544 channel->version.set = true;
545 break;
546 }
547 default:
548 ret = -1;
549 goto end;
550 }
551 }
552
553exit_loop:
882093ee 554 if (channel->reception_payload.buffer.size <
a58c490f
JG
555 (sizeof(struct lttng_notification_channel_message) +
556 sizeof(*reply))) {
557 /* Invalid message received. */
558 ret = -1;
559 goto end;
560 }
561
562 reply = (struct lttng_notification_channel_command_reply *)
882093ee 563 (channel->reception_payload.buffer.data +
a58c490f
JG
564 sizeof(struct lttng_notification_channel_message));
565 *status = (enum lttng_notification_channel_status) reply->status;
566end:
567 return ret;
568}
569
570static
571int handshake(struct lttng_notification_channel *channel)
572{
573 ssize_t ret;
574 enum lttng_notification_channel_status status =
575 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
576 struct lttng_notification_channel_command_handshake handshake = {
577 .major = LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR,
578 .minor = LTTNG_NOTIFICATION_CHANNEL_VERSION_MINOR,
579 };
57fb67ac 580 struct lttng_notification_channel_message msg_header;
a58c490f
JG
581 char send_buffer[sizeof(msg_header) + sizeof(handshake)];
582
57fb67ac
JG
583 msg_header.type = LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_HANDSHAKE;
584 msg_header.size = sizeof(handshake);
585 msg_header.fds = 0;
586
a58c490f
JG
587 memcpy(send_buffer, &msg_header, sizeof(msg_header));
588 memcpy(send_buffer + sizeof(msg_header), &handshake, sizeof(handshake));
589
590 pthread_mutex_lock(&channel->lock);
591
01ea340e 592 ret = lttcomm_send_creds_unix_sock(channel->socket, send_buffer,
a58c490f
JG
593 sizeof(send_buffer));
594 if (ret < 0) {
595 goto end_unlock;
596 }
597
598 /* Receive handshake info from the sessiond. */
599 ret = receive_command_reply(channel, &status);
600 if (ret < 0) {
601 goto end_unlock;
602 }
603
604 if (!channel->version.set) {
605 ret = -1;
606 goto end_unlock;
607 }
608
609 if (channel->version.major != LTTNG_NOTIFICATION_CHANNEL_VERSION_MAJOR) {
610 ret = -1;
611 goto end_unlock;
612 }
613
614end_unlock:
615 pthread_mutex_unlock(&channel->lock);
616 return ret;
617}
618
619static
620enum lttng_notification_channel_status send_condition_command(
621 struct lttng_notification_channel *channel,
622 enum lttng_notification_channel_message_type type,
623 const struct lttng_condition *condition)
624{
625 int socket;
3647288f 626 ssize_t ret;
a58c490f
JG
627 enum lttng_notification_channel_status status =
628 LTTNG_NOTIFICATION_CHANNEL_STATUS_OK;
c0a66c84 629 struct lttng_payload payload;
57fb67ac
JG
630 struct lttng_notification_channel_message cmd_header;
631
632 cmd_header.type = (int8_t) type;
633 cmd_header.size = 0;
634 cmd_header.fds = 0;
a58c490f 635
c0a66c84 636 lttng_payload_init(&payload);
3647288f 637
a58c490f
JG
638 if (!channel) {
639 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
640 goto end;
641 }
642
a0377dfe 643 LTTNG_ASSERT(type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE ||
a58c490f
JG
644 type == LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE);
645
646 pthread_mutex_lock(&channel->lock);
647 socket = channel->socket;
882093ee 648
a58c490f
JG
649 if (!lttng_condition_validate(condition)) {
650 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
651 goto end_unlock;
652 }
653
c0a66c84 654 ret = lttng_dynamic_buffer_append(&payload.buffer, &cmd_header,
3647288f
JG
655 sizeof(cmd_header));
656 if (ret) {
657 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
a58c490f
JG
658 goto end_unlock;
659 }
660
c0a66c84 661 ret = lttng_condition_serialize(condition, &payload);
3647288f
JG
662 if (ret) {
663 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_INVALID;
a58c490f
JG
664 goto end_unlock;
665 }
666
3647288f 667 /* Update payload length. */
c0a66c84
JG
668 ((struct lttng_notification_channel_message *) payload.buffer.data)->size =
669 (uint32_t) (payload.buffer.size - sizeof(cmd_header));
3647288f 670
882093ee
JR
671 {
672 struct lttng_payload_view pv =
673 lttng_payload_view_from_payload(
674 &payload, 0, -1);
675 const int fd_count =
676 lttng_payload_view_get_fd_handle_count(&pv);
677
678 /* Update fd count. */
679 ((struct lttng_notification_channel_message *) payload.buffer.data)->fds =
680 (uint32_t) fd_count;
681
682 ret = lttcomm_send_unix_sock(
683 socket, pv.buffer.data, pv.buffer.size);
684 if (ret < 0) {
685 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
686 goto end_unlock;
687 }
688
689 /* Pass fds if present. */
690 if (fd_count > 0) {
691 ret = lttcomm_send_payload_view_fds_unix_sock(socket,
692 &pv);
693 if (ret < 0) {
694 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
695 goto end_unlock;
696 }
697 }
a58c490f
JG
698 }
699
700 ret = receive_command_reply(channel, &status);
701 if (ret < 0) {
702 status = LTTNG_NOTIFICATION_CHANNEL_STATUS_ERROR;
703 goto end_unlock;
704 }
705end_unlock:
706 pthread_mutex_unlock(&channel->lock);
707end:
c0a66c84 708 lttng_payload_reset(&payload);
a58c490f
JG
709 return status;
710}
711
712enum lttng_notification_channel_status lttng_notification_channel_subscribe(
713 struct lttng_notification_channel *channel,
714 const struct lttng_condition *condition)
715{
716 return send_condition_command(channel,
717 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_SUBSCRIBE,
718 condition);
719}
720
721enum lttng_notification_channel_status lttng_notification_channel_unsubscribe(
722 struct lttng_notification_channel *channel,
723 const struct lttng_condition *condition)
724{
725 return send_condition_command(channel,
726 LTTNG_NOTIFICATION_CHANNEL_MESSAGE_TYPE_UNSUBSCRIBE,
727 condition);
728}
729
730void lttng_notification_channel_destroy(
731 struct lttng_notification_channel *channel)
732{
733 if (!channel) {
734 return;
735 }
736
737 if (channel->socket >= 0) {
738 (void) lttcomm_close_unix_sock(channel->socket);
739 }
740 pthread_mutex_destroy(&channel->lock);
882093ee 741 lttng_payload_reset(&channel->reception_payload);
a58c490f
JG
742 free(channel);
743}
This page took 0.074308 seconds and 4 git commands to generate.