Fix: notification: assert on len > 0 for dropped notification message
[lttng-tools.git] / src / lib / lttng-ctl / tracker.cpp
1 /*
2 * Copyright (C) 2020 Jérémie Galarneau <jeremie.galarneau@efficios.com>
3 *
4 * SPDX-License-Identifier: LGPL-2.1-only
5 *
6 */
7
8 #include <lttng/domain.h>
9 #include <lttng/lttng-error.h>
10
11 #include "lttng-ctl-helper.hpp"
12 #include <common/sessiond-comm/sessiond-comm.hpp>
13 #include <common/tracker.hpp>
14 #include <lttng/tracker.h>
15 #include <type_traits>
16
17 struct lttng_process_attr_tracker_handle {
18 char *session_name;
19 enum lttng_domain_type domain;
20 enum lttng_process_attr process_attr;
21 struct lttng_process_attr_values *inclusion_set;
22 };
23
24 void lttng_process_attr_tracker_handle_destroy(
25 struct lttng_process_attr_tracker_handle *tracker)
26 {
27 if (!tracker) {
28 return;
29 }
30
31 lttng_process_attr_values_destroy(tracker->inclusion_set);
32 free(tracker->session_name);
33 free(tracker);
34 }
35
36 enum lttng_error_code lttng_session_get_tracker_handle(const char *session_name,
37 enum lttng_domain_type domain,
38 enum lttng_process_attr process_attr,
39 struct lttng_process_attr_tracker_handle **out_tracker_handle)
40 {
41 enum lttng_error_code ret_code = LTTNG_OK;
42 struct lttng_process_attr_tracker_handle *handle = NULL;
43 enum lttng_process_attr_tracker_handle_status status;
44 enum lttng_tracking_policy policy;
45
46 if (!session_name || !out_tracker_handle) {
47 ret_code = LTTNG_ERR_INVALID;
48 goto error;
49 }
50
51 if (domain != LTTNG_DOMAIN_KERNEL && domain != LTTNG_DOMAIN_UST) {
52 ret_code = LTTNG_ERR_UNSUPPORTED_DOMAIN;
53 goto error;
54 }
55
56 handle = zmalloc<lttng_process_attr_tracker_handle>();
57 if (!handle) {
58 ret_code = LTTNG_ERR_NOMEM;
59 goto error;
60 }
61
62 handle->session_name = strdup(session_name);
63 if (!handle->session_name) {
64 ret_code = LTTNG_ERR_NOMEM;
65 goto error;
66 }
67
68 handle->domain = domain;
69 handle->process_attr = process_attr;
70
71 /*
72 * Use the `get_tracking_policy` command to validate the tracker's
73 * existence.
74 */
75 status = lttng_process_attr_tracker_handle_get_tracking_policy(
76 handle, &policy);
77 switch (status) {
78 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
79 break;
80 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
81 ret_code = LTTNG_ERR_SESSION_NOT_EXIST;
82 goto error;
83 default:
84 ret_code = LTTNG_ERR_UNK;
85 goto error;
86 }
87
88 *out_tracker_handle = handle;
89 return ret_code;
90 error:
91 lttng_process_attr_tracker_handle_destroy(handle);
92 return ret_code;
93 }
94
95 enum lttng_process_attr_tracker_handle_status
96 lttng_process_attr_tracker_handle_get_tracking_policy(
97 const struct lttng_process_attr_tracker_handle *tracker,
98 enum lttng_tracking_policy *policy)
99 {
100 void *reply = NULL;
101 int reply_ret, copy_ret;
102 enum lttng_process_attr_tracker_handle_status status =
103 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
104 struct lttcomm_session_msg lsm = {
105 .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_GET_POLICY,
106 .session = {},
107 .domain = {},
108 .u = {},
109 .fd_count = 0,
110 };
111
112 if (!tracker || !policy) {
113 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
114 goto end;
115 }
116
117 copy_ret = lttng_strncpy(lsm.session.name, tracker->session_name,
118 sizeof(lsm.session.name));
119 if (copy_ret) {
120 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
121 goto end;
122 }
123
124 lsm.domain.type = tracker->domain;
125 lsm.u.process_attr_tracker_get_tracking_policy.process_attr =
126 (int32_t) tracker->process_attr;
127
128 /* Command returns a session descriptor on success. */
129 reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
130 &lsm, NULL, 0, &reply);
131 if (reply_ret != sizeof(uint32_t)) {
132 if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST ||
133 reply_ret == -LTTNG_ERR_SESS_NOT_FOUND) {
134 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
135 } else {
136 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
137 }
138 goto end;
139 }
140
141 *policy = (enum lttng_tracking_policy)(*((const uint32_t *) reply));
142 end:
143 free(reply);
144 return status;
145 }
146
147 enum lttng_process_attr_tracker_handle_status
148 lttng_process_attr_tracker_handle_set_tracking_policy(
149 const struct lttng_process_attr_tracker_handle *tracker,
150 enum lttng_tracking_policy policy)
151 {
152 int reply_ret, copy_ret;
153 enum lttng_process_attr_tracker_handle_status status =
154 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
155 struct lttcomm_session_msg lsm = {
156 .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_SET_POLICY,
157 .session = {},
158 .domain = {},
159 .u = {},
160 .fd_count = 0,
161 };
162
163 if (!tracker) {
164 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
165 goto end;
166 }
167
168 copy_ret = lttng_strncpy(lsm.session.name, tracker->session_name,
169 sizeof(lsm.session.name));
170 if (copy_ret) {
171 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
172 goto end;
173 }
174
175 lsm.domain.type = tracker->domain;
176 lsm.u.process_attr_tracker_set_tracking_policy.process_attr =
177 (int32_t) tracker->process_attr;
178 lsm.u.process_attr_tracker_set_tracking_policy.tracking_policy =
179 (int32_t) policy;
180
181 /* Command returns a session descriptor on success. */
182 reply_ret = lttng_ctl_ask_sessiond(&lsm, NULL);
183 if (reply_ret < 0) {
184 if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST) {
185 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
186 } else {
187 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
188 }
189 goto end;
190 }
191 end:
192 return status;
193 }
194
195 #define DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(command_upper, \
196 command_lower, process_attr_name, value_type_name, \
197 value_type_c, value_type_enum) \
198 enum lttng_process_attr_tracker_handle_status \
199 lttng_process_attr_##process_attr_name##_tracker_handle_##command_lower##_##value_type_name( \
200 const struct lttng_process_attr_tracker_handle \
201 *tracker, \
202 value_type_c value) \
203 { \
204 int ret; \
205 enum lttng_process_attr_tracker_handle_status status = \
206 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; \
207 struct lttcomm_session_msg lsm = { \
208 .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_##command_upper##_INCLUDE_VALUE, \
209 .session = {}, \
210 .domain = {}, \
211 .u = {}, \
212 .fd_count = 0, \
213 }; \
214 \
215 if (!tracker) { \
216 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
217 goto end; \
218 } \
219 \
220 ret = lttng_strncpy(lsm.session.name, tracker->session_name, \
221 sizeof(lsm.session.name)); \
222 if (ret) { \
223 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
224 goto end; \
225 } \
226 \
227 lsm.domain.type = tracker->domain; \
228 lsm.u.process_attr_tracker_add_remove_include_value \
229 .process_attr = \
230 (int32_t) tracker->process_attr; \
231 lsm.u.process_attr_tracker_add_remove_include_value \
232 .value_type = (uint32_t) \
233 LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum; \
234 \
235 if (std::is_signed<value_type_c>::value) { \
236 lsm.u.process_attr_tracker_add_remove_include_value \
237 .integral_value.u._signed = value; \
238 } else { \
239 lsm.u.process_attr_tracker_add_remove_include_value \
240 .integral_value.u._unsigned = value; \
241 } \
242 \
243 ret = lttng_ctl_ask_sessiond(&lsm, NULL); \
244 if (ret < 0) { \
245 switch (-ret) { \
246 case LTTNG_ERR_PROCESS_ATTR_EXISTS: \
247 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS; \
248 break; \
249 case LTTNG_ERR_PROCESS_ATTR_MISSING: \
250 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING; \
251 break; \
252 case LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY: \
253 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; \
254 break; \
255 default: \
256 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; \
257 } \
258 } \
259 end: \
260 return status; \
261 }
262
263 #define DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(command_upper, \
264 command_lower, process_attr_name, value_type_name, \
265 value_type_enum) \
266 enum lttng_process_attr_tracker_handle_status \
267 lttng_process_attr_##process_attr_name##_tracker_handle_##command_lower##_##value_type_name( \
268 const struct lttng_process_attr_tracker_handle \
269 *tracker, \
270 const char *value) \
271 { \
272 int ret; \
273 enum lttng_process_attr_tracker_handle_status status = \
274 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK; \
275 struct lttcomm_session_msg lsm = { \
276 .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_##command_upper##_INCLUDE_VALUE, \
277 .session = {}, \
278 .domain = {}, \
279 .u = {}, \
280 .fd_count = 0, \
281 }; \
282 const size_t len = value ? strlen(value) + 1 : 0; \
283 \
284 if (!tracker || !value) { \
285 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
286 goto end; \
287 } \
288 \
289 ret = lttng_strncpy(lsm.session.name, tracker->session_name, \
290 sizeof(lsm.session.name)); \
291 if (ret) { \
292 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID; \
293 goto end; \
294 } \
295 \
296 lsm.domain.type = tracker->domain; \
297 lsm.u.process_attr_tracker_add_remove_include_value \
298 .process_attr = \
299 (int32_t) tracker->process_attr; \
300 lsm.u.process_attr_tracker_add_remove_include_value.name_len = \
301 (uint32_t) len; \
302 lsm.u.process_attr_tracker_add_remove_include_value \
303 .value_type = (uint32_t) \
304 LTTNG_PROCESS_ATTR_VALUE_TYPE_##value_type_enum; \
305 \
306 ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header( \
307 &lsm, value, len, NULL); \
308 if (ret < 0) { \
309 switch (-ret) { \
310 case LTTNG_ERR_PROCESS_ATTR_EXISTS: \
311 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS; \
312 break; \
313 case LTTNG_ERR_PROCESS_ATTR_MISSING: \
314 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING; \
315 break; \
316 case LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY: \
317 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY; \
318 break; \
319 case LTTNG_ERR_USER_NOT_FOUND: \
320 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_USER_NOT_FOUND; \
321 break; \
322 case LTTNG_ERR_GROUP_NOT_FOUND: \
323 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_GROUP_NOT_FOUND; \
324 break; \
325 default: \
326 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR; \
327 } \
328 } \
329 end: \
330 return status; \
331 }
332
333 /* PID */
334 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
335 ADD, add, process_id, pid, pid_t, PID);
336 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
337 REMOVE, remove, process_id, pid, pid_t, PID);
338
339 /* VPID */
340 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
341 ADD, add, virtual_process_id, pid, pid_t, PID);
342 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
343 REMOVE, remove, virtual_process_id, pid, pid_t, PID);
344
345 /* UID */
346 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
347 ADD, add, user_id, uid, uid_t, UID);
348 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
349 REMOVE, remove, user_id, uid, uid_t, UID);
350 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
351 ADD, add, user_id, user_name, USER_NAME);
352 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
353 REMOVE, remove, user_id, user_name, USER_NAME);
354
355 /* VUID */
356 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
357 ADD, add, virtual_user_id, uid, uid_t, UID);
358 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
359 REMOVE, remove, virtual_user_id, uid, uid_t, UID);
360 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
361 ADD, add, virtual_user_id, user_name, USER_NAME);
362 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
363 REMOVE, remove, virtual_user_id, user_name, USER_NAME);
364
365 /* GID */
366 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
367 ADD, add, group_id, gid, gid_t, GID);
368 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
369 REMOVE, remove, group_id, gid, gid_t, GID);
370 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
371 ADD, add, group_id, group_name, GROUP_NAME);
372 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
373 REMOVE, remove, group_id, group_name, GROUP_NAME);
374
375 /* VGID */
376 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
377 ADD, add, virtual_group_id, gid, gid_t, GID);
378 DEFINE_TRACKER_ADD_REMOVE_INTEGRAL_VALUE_FUNC(
379 REMOVE, remove, virtual_group_id, gid, gid_t, GID);
380 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
381 ADD, add, virtual_group_id, group_name, GROUP_NAME);
382 DEFINE_TRACKER_ADD_REMOVE_STRING_VALUE_FUNC(
383 REMOVE, remove, virtual_group_id, group_name, GROUP_NAME);
384
385 enum lttng_process_attr_tracker_handle_status
386 lttng_process_attr_tracker_handle_get_inclusion_set(
387 struct lttng_process_attr_tracker_handle *tracker,
388 const struct lttng_process_attr_values **values)
389 {
390 char *reply = NULL;
391 int reply_ret, copy_ret;
392 enum lttng_process_attr_tracker_handle_status status =
393 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK;
394 struct lttcomm_session_msg lsm = {
395 .cmd_type = LTTNG_PROCESS_ATTR_TRACKER_GET_INCLUSION_SET,
396 .session = {},
397 .domain = {},
398 .u = {},
399 .fd_count = 0,
400 };
401 struct lttng_buffer_view inclusion_set_view;
402 ssize_t inclusion_set_ret;
403
404 if (!tracker || !values) {
405 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
406 goto end;
407 }
408
409 lttng_process_attr_values_destroy(tracker->inclusion_set);
410 tracker->inclusion_set = NULL;
411
412 copy_ret = lttng_strncpy(lsm.session.name, tracker->session_name,
413 sizeof(lsm.session.name));
414 if (copy_ret) {
415 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID;
416 goto end;
417 }
418
419 lsm.domain.type = tracker->domain;
420 lsm.u.process_attr_tracker_get_tracking_policy.process_attr =
421 (int32_t) tracker->process_attr;
422
423 /* Command returns a session descriptor on success. */
424 reply_ret = lttng_ctl_ask_sessiond_varlen_no_cmd_header(
425 &lsm, NULL, 0, (void **) &reply);
426 if (reply_ret < 0) {
427 if (reply_ret == -LTTNG_ERR_SESSION_NOT_EXIST) {
428 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST;
429 } else if (reply_ret ==
430 -LTTNG_ERR_PROCESS_ATTR_TRACKER_INVALID_TRACKING_POLICY) {
431 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY;
432 } else {
433 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR;
434 }
435 goto end;
436 } else if (reply_ret == 0) {
437 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
438 goto end;
439 }
440
441 inclusion_set_view = lttng_buffer_view_init(reply, 0, reply_ret);
442 if (!inclusion_set_view.data) {
443 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
444 goto end;
445 }
446
447 inclusion_set_ret = lttng_process_attr_values_create_from_buffer(
448 tracker->domain, tracker->process_attr,
449 &inclusion_set_view, &tracker->inclusion_set);
450 if (inclusion_set_ret < 0) {
451 status = LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR;
452 goto end;
453 }
454 *values = tracker->inclusion_set;
455 end:
456 free(reply);
457 return status;
458 }
459
460 enum lttng_process_attr_values_status lttng_process_attr_values_get_count(
461 const struct lttng_process_attr_values *values,
462 unsigned int *count)
463 {
464 enum lttng_process_attr_values_status status =
465 LTTNG_PROCESS_ATTR_VALUES_STATUS_OK;
466
467 if (!values || !count) {
468 status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID;
469 goto end;
470 }
471
472 *count = _lttng_process_attr_values_get_count(values);
473 end:
474 return status;
475 }
476
477 enum lttng_process_attr_value_type lttng_process_attr_values_get_type_at_index(
478 const struct lttng_process_attr_values *values,
479 unsigned int index)
480 {
481 enum lttng_process_attr_value_type type;
482 const struct process_attr_value *value;
483
484 if (!values) {
485 type = LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID;
486 goto end;
487 }
488
489 if (_lttng_process_attr_values_get_count(values) <= index) {
490 type = LTTNG_PROCESS_ATTR_VALUE_TYPE_INVALID;
491 goto end;
492 }
493
494 value = lttng_process_attr_tracker_values_get_at_index(values, index);
495 type = value->type;
496 end:
497 return type;
498 }
499
500 #define DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER( \
501 value_type_name, value_type, expected_value_type) \
502 enum lttng_process_attr_values_status \
503 lttng_process_attr_values_get_##value_type_name##_at_index( \
504 const struct lttng_process_attr_values \
505 *values, \
506 unsigned int index, \
507 value_type *out_value) \
508 { \
509 enum lttng_process_attr_values_status status = \
510 LTTNG_PROCESS_ATTR_VALUES_STATUS_OK; \
511 const struct process_attr_value *value; \
512 \
513 if (!values) { \
514 status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; \
515 goto end; \
516 } \
517 \
518 if (_lttng_process_attr_values_get_count(values) <= index) { \
519 status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID; \
520 goto end; \
521 } \
522 \
523 value = lttng_process_attr_tracker_values_get_at_index( \
524 values, index); \
525 if (value->type != \
526 LTTNG_PROCESS_ATTR_VALUE_TYPE_##expected_value_type) { \
527 status = LTTNG_PROCESS_ATTR_VALUES_STATUS_INVALID_TYPE; \
528 goto end; \
529 } \
530 *out_value = value->value.value_type_name; \
531 end: \
532 return status; \
533 }
534
535 DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(pid, pid_t, PID);
536 DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(uid, uid_t, UID);
537 DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(gid, gid_t, GID);
538 DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(user_name, const char *, USER_NAME);
539 DEFINE_LTTNG_PROCESS_ATTR_VALUES_GETTER(group_name, const char *, GROUP_NAME);
540
541 static enum lttng_error_code handle_status_to_error_code(
542 enum lttng_process_attr_tracker_handle_status handle_status)
543 {
544 switch (handle_status) {
545 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY:
546 return LTTNG_ERR_INVALID;
547 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_SESSION_DOES_NOT_EXIST:
548 return LTTNG_ERR_SESSION_NOT_EXIST;
549 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_COMMUNICATION_ERROR:
550 return LTTNG_ERR_INVALID_PROTOCOL;
551 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_EXISTS:
552 return LTTNG_ERR_PID_TRACKED;
553 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_MISSING:
554 return LTTNG_ERR_PID_NOT_TRACKED;
555 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK:
556 return LTTNG_OK;
557 case LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_ERROR:
558 default:
559 /* fall-through. */
560 return LTTNG_ERR_UNK;
561 }
562 }
563
564 /*
565 * Add PID to session tracker.
566 * Return 0 on success else a negative LTTng error code.
567 */
568 int lttng_track_pid(struct lttng_handle *handle, int pid)
569 {
570 enum lttng_error_code ret_code;
571 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
572 enum lttng_process_attr_tracker_handle_status handle_status;
573 enum lttng_tracking_policy policy;
574 enum lttng_process_attr process_attr;
575
576 if (!handle) {
577 ret_code = LTTNG_ERR_INVALID;
578 goto end;
579 }
580
581 process_attr = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
582 LTTNG_PROCESS_ATTR_PROCESS_ID :
583 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID;
584
585 ret_code = lttng_session_get_tracker_handle(handle->session_name,
586 handle->domain.type,
587 process_attr, &tracker_handle);
588 if (ret_code != LTTNG_OK) {
589 goto end;
590 }
591
592 if (pid == -1) {
593 handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
594 tracker_handle,
595 LTTNG_TRACKING_POLICY_INCLUDE_ALL);
596 ret_code = handle_status_to_error_code(handle_status);
597 goto end;
598 }
599
600 handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
601 tracker_handle, &policy);
602 if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
603 ret_code = handle_status_to_error_code(handle_status);
604 goto end;
605 }
606
607 if (policy != LTTNG_TRACKING_POLICY_INCLUDE_SET) {
608 handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
609 tracker_handle,
610 LTTNG_TRACKING_POLICY_INCLUDE_SET);
611 if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
612 ret_code = handle_status_to_error_code(handle_status);
613 goto end;
614 }
615 }
616
617 handle_status = process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID ?
618 lttng_process_attr_process_id_tracker_handle_add_pid(
619 tracker_handle,
620 (pid_t) pid) :
621 lttng_process_attr_virtual_process_id_tracker_handle_add_pid(
622 tracker_handle,
623 (pid_t) pid);
624 ret_code = handle_status_to_error_code(handle_status);
625 end:
626 lttng_process_attr_tracker_handle_destroy(tracker_handle);
627 return ret_code == LTTNG_OK ? 0 : -ret_code;
628 }
629
630 /*
631 * Remove PID from session tracker.
632 * Return 0 on success else a negative LTTng error code.
633 */
634 int lttng_untrack_pid(struct lttng_handle *handle, int pid)
635 {
636 enum lttng_error_code ret_code;
637 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
638 enum lttng_process_attr_tracker_handle_status handle_status;
639 enum lttng_tracking_policy policy;
640 enum lttng_process_attr process_attr;
641
642 if (!handle) {
643 ret_code = LTTNG_ERR_INVALID;
644 goto end;
645 }
646
647 process_attr = handle->domain.type == LTTNG_DOMAIN_KERNEL ?
648 LTTNG_PROCESS_ATTR_PROCESS_ID :
649 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID;
650 ret_code = lttng_session_get_tracker_handle(handle->session_name,
651 handle->domain.type, process_attr, &tracker_handle);
652 if (ret_code != LTTNG_OK) {
653 goto end;
654 }
655
656 if (pid == -1) {
657 handle_status = lttng_process_attr_tracker_handle_set_tracking_policy(
658 tracker_handle,
659 LTTNG_TRACKING_POLICY_EXCLUDE_ALL);
660 ret_code = handle_status_to_error_code(handle_status);
661 goto end;
662 }
663
664 handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
665 tracker_handle, &policy);
666 if (handle_status != LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
667 ret_code = handle_status_to_error_code(handle_status);
668 goto end;
669 }
670
671 if (policy == LTTNG_TRACKING_POLICY_EXCLUDE_ALL) {
672 ret_code = LTTNG_ERR_PID_NOT_TRACKED;
673 goto end;
674 } else if (policy == LTTNG_TRACKING_POLICY_INCLUDE_ALL) {
675 ret_code = LTTNG_ERR_INVALID;
676 goto end;
677 }
678
679 handle_status = process_attr == LTTNG_PROCESS_ATTR_PROCESS_ID ?
680 lttng_process_attr_process_id_tracker_handle_remove_pid(
681 tracker_handle,
682 (pid_t) pid) :
683 lttng_process_attr_virtual_process_id_tracker_handle_remove_pid(
684 tracker_handle,
685 (pid_t) pid);
686 if (handle_status == LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY) {
687 ret_code = LTTNG_ERR_PID_NOT_TRACKED;
688 }
689 end:
690 lttng_process_attr_tracker_handle_destroy(tracker_handle);
691 return ret_code == LTTNG_OK ? 0 : -ret_code;
692 }
693
694 /*
695 * List PIDs in the tracker.
696 *
697 * enabled is set to whether the PID tracker is enabled.
698 * pids is set to an allocated array of PIDs currently tracked. On
699 * success, pids must be freed by the caller.
700 * nr_pids is set to the number of entries contained by the pids array.
701 *
702 * Returns 0 on success, else a negative LTTng error code.
703 */
704 int lttng_list_tracker_pids(struct lttng_handle *handle,
705 int *_enabled,
706 int32_t **_pids,
707 size_t *_nr_pids)
708 {
709 enum lttng_error_code ret_code;
710 struct lttng_process_attr_tracker_handle *tracker_handle = NULL;
711 enum lttng_process_attr_tracker_handle_status handle_status;
712 const struct lttng_process_attr_values *values;
713 enum lttng_tracking_policy policy;
714 unsigned int pid_count, i;
715 int32_t *pid_array = NULL;
716
717 if (!handle || !_enabled || !_pids || !_nr_pids) {
718 ret_code = LTTNG_ERR_INVALID;
719 goto end;
720 }
721
722 ret_code = lttng_session_get_tracker_handle(handle->session_name,
723 handle->domain.type,
724 LTTNG_PROCESS_ATTR_VIRTUAL_PROCESS_ID, &tracker_handle);
725 if (ret_code != LTTNG_OK) {
726 goto end;
727 }
728
729 while (true) {
730 handle_status = lttng_process_attr_tracker_handle_get_inclusion_set(
731 tracker_handle, &values);
732 if (handle_status ==
733 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
734 policy = LTTNG_TRACKING_POLICY_INCLUDE_SET;
735 break;
736 } else if (handle_status !=
737 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_INVALID_TRACKING_POLICY) {
738 ret_code = handle_status_to_error_code(handle_status);
739 goto end;
740 }
741
742 handle_status = lttng_process_attr_tracker_handle_get_tracking_policy(
743 tracker_handle, &policy);
744 if (handle_status !=
745 LTTNG_PROCESS_ATTR_TRACKER_HANDLE_STATUS_OK) {
746 ret_code = handle_status_to_error_code(handle_status);
747 goto end;
748 }
749
750 /* Tracking policy changed in the meantime, retry. */
751 if (policy == LTTNG_TRACKING_POLICY_INCLUDE_SET) {
752 continue;
753 }
754 break;
755 }
756
757 switch (policy) {
758 case LTTNG_TRACKING_POLICY_INCLUDE_ALL:
759 *_enabled = 0;
760 goto end;
761 case LTTNG_TRACKING_POLICY_EXCLUDE_ALL:
762 *_enabled = 1;
763 pid_count = 0;
764 break;
765 case LTTNG_TRACKING_POLICY_INCLUDE_SET:
766 {
767 const enum lttng_process_attr_values_status values_status =
768 lttng_process_attr_values_get_count(
769 values, &pid_count);
770
771 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
772 ret_code = LTTNG_ERR_UNK;
773 goto end;
774 }
775 break;
776 }
777 default:
778 ret_code = LTTNG_ERR_INVALID_PROTOCOL;
779 goto end;
780 }
781
782 pid_array = calloc<int32_t>(pid_count);
783 if (!pid_array) {
784 ret_code = LTTNG_ERR_NOMEM;
785 goto end;
786 }
787
788 /* Extract values to a raw array. */
789 for (i = 0; i < pid_count; i++) {
790 pid_t pid;
791 const enum lttng_process_attr_values_status values_status =
792 lttng_process_attr_values_get_pid_at_index(
793 values, i, &pid);
794
795 if (values_status != LTTNG_PROCESS_ATTR_VALUES_STATUS_OK) {
796 ret_code = LTTNG_ERR_UNK;
797 goto end;
798 }
799 pid_array[i] = (int32_t) pid;
800 }
801 *_nr_pids = (size_t) pid_count;
802 *_pids = pid_array;
803 pid_array = NULL;
804 end:
805 lttng_process_attr_tracker_handle_destroy(tracker_handle);
806 free(pid_array);
807 return ret_code == LTTNG_OK ? 0 : -ret_code;
808 }
This page took 0.045987 seconds and 4 git commands to generate.