Cygwin: Pass file paths instead of file descriptors over UNIX sockets
[lttng-ust.git] / tests / ust-basic-tracing / ust-basic-tracing.c
CommitLineData
b0a99af4
MD
1/*
2 * ust-basic-tracing.c - Basic single-session, single-channel, single-process UST tracing
3 *
4 * Copyright (C) 2011 - Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
5 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
6 *
e92f3e28
MD
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; version 2 of the License only.
b0a99af4 10 *
e92f3e28
MD
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
b0a99af4 15 *
e92f3e28
MD
16 * You should have received a copy of the GNU General Public License along
17 * with this program; if not, write to the Free Software Foundation, Inc.,
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
b0a99af4
MD
19 */
20
21#define _LARGEFILE64_SOURCE
9d335227 22#define _GNU_SOURCE
b0a99af4
MD
23#include <errno.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <signal.h>
28#include <unistd.h>
29#include <sys/wait.h>
30#include <sys/types.h>
31#include <sys/stat.h>
07dd0d60
MD
32#include <sys/time.h>
33#include <sys/resource.h>
b0a99af4
MD
34#include <fcntl.h>
35#include <sys/mman.h>
36#include <limits.h>
37#include <urcu/futex.h>
38#include <urcu/uatomic.h>
39#include <assert.h>
40#include <sys/socket.h>
41
a3bb4b27 42#include <ust-comm.h>
b0a99af4
MD
43#include "../../libringbuffer/backend.h"
44#include "../../libringbuffer/frontend.h"
45
46#define MAX_NR_STREAMS 64
47#define MAX_NR_EVENTS 128
48
b0a99af4 49static int session_handle;
61f02aea
MD
50static struct lttng_ust_object_data metadata_stream_data;
51static struct lttng_ust_object_data metadata_data;
52static struct lttng_ust_object_data channel_data;
53static struct lttng_ust_object_data stream_data[MAX_NR_STREAMS];
b0a99af4 54static int event_handle[MAX_NR_EVENTS];
8de38cf7 55static int context_handle;
b0a99af4
MD
56
57static int apps_socket = -1;
58static char apps_sock_path[PATH_MAX];
59static char local_apps_wait_shm_path[PATH_MAX];
60
61static volatile int quit_program;
62
63static void handle_signals(int signo)
64{
65 quit_program = 1;
66}
67
b0a99af4 68static
61f02aea 69int open_streams(int sock, int channel_handle, struct lttng_ust_object_data *stream_datas,
b0a99af4
MD
70 int nr_check)
71{
72 int ret, k = 0;
73
74 for (;;) {
57773204
MD
75 struct ustcomm_ust_msg lum;
76 struct ustcomm_ust_reply lur;
b0a99af4
MD
77
78 memset(&lum, 0, sizeof(lum));
79 lum.handle = channel_handle;
80 lum.cmd = LTTNG_UST_STREAM;
57773204 81 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
82 if (!ret) {
83 assert(k < nr_check);
84 stream_datas[k].handle = lur.ret_val;
85 printf("received stream handle %u\n",
86 stream_datas[k].handle);
57773204 87 if (lur.ret_code == USTCOMM_OK) {
b0a99af4
MD
88 ssize_t len;
89
90 stream_datas[k].memory_map_size = lur.u.stream.memory_map_size;
91 /* get shm fd */
57773204 92 len = ustcomm_recv_fd(sock);
b0a99af4
MD
93 if (len < 0)
94 return -EINVAL;
95 stream_datas[k].shm_fd = len;
96 /* get wait fd */
57773204 97 len = ustcomm_recv_fd(sock);
b0a99af4
MD
98 if (len < 0)
99 return -EINVAL;
100 stream_datas[k].wait_fd = len;
101 }
102 k++;
103 }
104 if (ret == -ENOENT)
105 break;
106 if (ret)
107 return ret;
108 }
109 return 0;
110}
111
112static
61f02aea 113int close_streams(int sock, struct lttng_ust_object_data *stream_datas, int nr_check)
b0a99af4
MD
114{
115 int ret, k;
116
117 for (k = 0; k < nr_check; k++) {
57773204
MD
118 struct ustcomm_ust_msg lum;
119 struct ustcomm_ust_reply lur;
b0a99af4
MD
120
121 if (!stream_datas[k].handle)
122 continue;
123 memset(&lum, 0, sizeof(lum));
124 lum.handle = stream_datas[k].handle;
125 lum.cmd = LTTNG_UST_RELEASE;
57773204 126 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
127 if (ret) {
128 printf("Error closing stream\n");
129 return ret;
130 }
131 if (stream_datas[k].shm_fd >= 0) {
132 ret = close(stream_datas[k].shm_fd);
133 if (ret) {
134 printf("Error closing stream shm_fd\n");
135 return ret;
136 }
137 }
138 if (stream_datas[k].wait_fd >= 0) {
139 ret = close(stream_datas[k].wait_fd);
140 if (ret) {
141 printf("Error closing stream wait_fd\n");
142 return ret;
143 }
144 }
145 }
146 return 0;
147}
148
149static
38fae1d3 150struct lttng_ust_shm_handle *map_channel(struct lttng_ust_object_data *chan_data,
61f02aea 151 struct lttng_ust_object_data *stream_datas, int nr_check)
b0a99af4 152{
38fae1d3 153 struct lttng_ust_shm_handle *handle;
b0a99af4
MD
154 struct channel *chan;
155 int k, ret;
156
157 /* map metadata channel */
158 handle = channel_handle_create(chan_data->shm_fd,
159 chan_data->wait_fd,
160 chan_data->memory_map_size);
161 if (!handle) {
162 printf("create handle error\n");
163 return NULL;
164 }
165 chan_data->shm_fd = -1;
166 chan_data->wait_fd = -1;
167 chan = shmp(handle, handle->chan);
168
169 for (k = 0; k < nr_check; k++) {
61f02aea 170 struct lttng_ust_object_data *stream_data = &stream_datas[k];
b0a99af4
MD
171
172 if (!stream_data->handle)
173 break;
174 /* map stream */
175 ret = channel_handle_add_stream(handle,
176 stream_data->shm_fd,
177 stream_data->wait_fd,
178 stream_data->memory_map_size);
179 if (ret) {
180 printf("add stream error\n");
181 goto error_destroy;
182 }
183 stream_data->shm_fd = -1;
184 stream_data->wait_fd = -1;
185 }
186 return handle;
187
188error_destroy:
189 channel_destroy(chan, handle, 1);
190 return NULL;
191}
192
193static
38fae1d3 194void unmap_channel(struct lttng_ust_shm_handle *handle)
b0a99af4
MD
195{
196 struct channel *chan;
197
198 chan = shmp(handle, handle->chan);
199 /* unmap channel */
200 channel_destroy(chan, handle, 1);
201}
202
203static
38fae1d3 204int consume_stream(struct lttng_ust_shm_handle *handle, int cpu, char *outfile)
b0a99af4
MD
205{
206 struct channel *chan;
4cfec15c 207 struct lttng_ust_lib_ring_buffer *buf;
b0a99af4 208 int outfd, ret;
ef9ff354 209 int *shm_fd, *wait_fd;
bf5ff35e 210 char *shm_path, *wait_pipe_path;
ef9ff354 211 uint64_t *memory_map_size;
b0a99af4
MD
212
213 chan = shmp(handle, handle->chan);
214
215 /* open stream */
216 buf = channel_get_ring_buffer(&chan->backend.config,
bf5ff35e
CB
217 chan, cpu, handle,
218 &shm_fd, &shm_path,
219 &wait_fd, &wait_pipe_path,
220 &memory_map_size);
b0a99af4
MD
221 if (!buf)
222 return -ENOENT;
223 ret = lib_ring_buffer_open_read(buf, handle, 1);
224 if (ret) {
225 return -1;
226 }
227
228 /* copy */
1abcee5d 229 outfd = open(outfile, O_WRONLY | O_CREAT | O_TRUNC,
b0a99af4
MD
230 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
231 if (outfd < 0) {
232 perror("open output");
233 return -1;
234 }
235
236 printf("Waiting for buffer data for %s\n", outfile);
237 for (;;) {
238 unsigned long read_size;
239 unsigned long copy_size;
240 char *ptr;
241
242 ret = lib_ring_buffer_get_next_subbuf(buf, handle);
243 printf("get next ret %d\n", ret);
244 if (ret == -ENODATA)
245 break;
246 if (ret == -EAGAIN) {
247 sleep(1);
248 continue;
249 }
250 if (ret) {
251 printf("Error %d in lib_ring_buffer_get_next_subbuf\n", ret);
252 return -1;
253 }
254 read_size = lib_ring_buffer_get_read_data_size(
255 &chan->backend.config, buf, handle);
256 read_size = PAGE_ALIGN(read_size);
257 ptr = lib_ring_buffer_read_offset_address(
258 &buf->backend, 0, handle);
259 printf("WRITE: copy %lu bytes\n", read_size);
260 copy_size = write(outfd, ptr, read_size);
261 if (copy_size < read_size) {
f97e7ae1 262 printf("write issue: copied %lu, expected %lu\n", copy_size, read_size);
b0a99af4
MD
263 }
264 lib_ring_buffer_put_next_subbuf(buf, handle);
265 }
266
267 ret = close(outfd);
268 if (ret) {
269 perror("close");
270 return -1;
271 }
272
273 /* close stream */
274 lib_ring_buffer_release_read(buf, handle, 1);
275 return 0;
276}
277
278static
279int consume_buffers(const char *outputpath)
280{
281 int k, ret;
282 mode_t old_umask;
283 char pathname[PATH_MAX];
38fae1d3 284 struct lttng_ust_shm_handle *handle;
b0a99af4
MD
285
286 snprintf(pathname, PATH_MAX - 1, "%s", outputpath);
287 old_umask = umask(0);
288 ret = mkdir(pathname, S_IRWXU | S_IRWXG);
289 if (ret && errno != EEXIST) {
290 perror("mkdir");
291 umask(old_umask);
292 return -1;
293 }
294 umask(old_umask);
295
296 /* copy metadata */
297 handle = map_channel(&metadata_data,
298 &metadata_stream_data, 1);
299 if (!handle)
300 return -1;
301 snprintf(pathname, PATH_MAX - 1,
302 "%s/metadata", outputpath);
303 ret = consume_stream(handle, -1, pathname);
304 if (ret && ret != -ENOENT) {
305 printf("Error in consume_stream\n");
306 return ret;
307 }
308 unmap_channel(handle);
309
310 /* copy binary data */
311 handle = map_channel(&channel_data,
312 stream_data, MAX_NR_STREAMS);
313 if (!handle)
314 return -1;
315 for (k = 0; k < MAX_NR_STREAMS; k++) {
316 snprintf(pathname, PATH_MAX - 1,
317 "%s/data_%u", outputpath, k);
318 ret = consume_stream(handle, k, pathname);
319 if (ret && ret != -ENOENT) {
320 printf("Error in consume_stream\n");
321 return ret;
322 }
323 }
324 unmap_channel(handle);
325
326 return 0;
327}
328
57773204 329static
b0a99af4
MD
330int send_app_msgs(int sock, const char *outputpath,
331 unsigned int nr_events, const char **event_names)
332{
57773204
MD
333 struct ustcomm_ust_msg lum;
334 struct ustcomm_ust_reply lur;
b0a99af4
MD
335 int ret, k;
336
337 /* Create session */
338 memset(&lum, 0, sizeof(lum));
339 lum.handle = LTTNG_UST_ROOT_HANDLE;
340 lum.cmd = LTTNG_UST_SESSION;
57773204 341 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
342 if (ret)
343 return ret;
344 session_handle = lur.ret_val;
345 printf("received session handle %u\n", session_handle);
346
347 /* Create metadata channel */
348 memset(&lum, 0, sizeof(lum));
349 lum.handle = session_handle;
350 lum.cmd = LTTNG_UST_METADATA;
351 lum.u.channel.overwrite = 0;
352 lum.u.channel.subbuf_size = 32768;
353 lum.u.channel.num_subbuf = 4;
354 lum.u.channel.switch_timer_interval = 0;
355 lum.u.channel.read_timer_interval = 0;
356 lum.u.channel.output = LTTNG_UST_MMAP;
57773204 357 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
358 if (ret)
359 return ret;
360 metadata_data.handle = lur.ret_val;
361 printf("received metadata handle %u\n", metadata_data.handle);
57773204 362 if (lur.ret_code == USTCOMM_OK) {
b0a99af4
MD
363 ssize_t len;
364
365 metadata_data.memory_map_size = lur.u.channel.memory_map_size;
366 /* get shm fd */
57773204 367 len = ustcomm_recv_fd(sock);
b0a99af4
MD
368 if (len < 0)
369 return -EINVAL;
370 metadata_data.shm_fd = len;
371 /* get wait fd */
57773204 372 len = ustcomm_recv_fd(sock);
b0a99af4
MD
373 if (len < 0)
374 return -EINVAL;
375 metadata_data.wait_fd = len;
376 }
377
378 ret = open_streams(sock, metadata_data.handle,
379 &metadata_stream_data, 1);
380 if (ret) {
381 printf("Error in open_streams\n");
382 return ret;
383 }
384
385 /* Create data channel */
386 memset(&lum, 0, sizeof(lum));
387 lum.handle = session_handle;
388 lum.cmd = LTTNG_UST_CHANNEL;
389 //lum.u.channel.overwrite = 0;
390 lum.u.channel.overwrite = 1;
391 lum.u.channel.subbuf_size = 32768;
392 lum.u.channel.num_subbuf = 8;
393 //lum.u.channel.num_subbuf = 4;
394 //lum.u.channel.num_subbuf = 2;
395 lum.u.channel.switch_timer_interval = 0;
396 lum.u.channel.read_timer_interval = 0;
397 lum.u.channel.output = LTTNG_UST_MMAP;
57773204 398 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
399 if (ret)
400 return ret;
401 channel_data.handle = lur.ret_val;
402 printf("received channel handle %u\n", channel_data.handle);
57773204 403 if (lur.ret_code == USTCOMM_OK) {
b0a99af4
MD
404 ssize_t len;
405
406 channel_data.memory_map_size = lur.u.channel.memory_map_size;
407 /* get shm fd */
57773204 408 len = ustcomm_recv_fd(sock);
b0a99af4
MD
409 if (len < 0)
410 return -EINVAL;
411 channel_data.shm_fd = len;
412 /* get wait fd */
57773204 413 len = ustcomm_recv_fd(sock);
b0a99af4
MD
414 if (len < 0)
415 return -EINVAL;
416 channel_data.wait_fd = len;
417 }
418
419 /* Create events */
420 for (k = 0; k < nr_events; k++) {
421 memset(&lum, 0, sizeof(lum));
422 lum.handle = channel_data.handle;
423 lum.cmd = LTTNG_UST_EVENT;
424 strncpy(lum.u.event.name, event_names[k],
425 LTTNG_UST_SYM_NAME_LEN);
426 lum.u.event.instrumentation = LTTNG_UST_TRACEPOINT;
57773204 427 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
428 if (ret)
429 return ret;
430 event_handle[k] = lur.ret_val;
431 printf("received event handle %u\n", event_handle[k]);
432 }
433
3b402b40 434 /* Attach vtid context */
8de38cf7
MD
435 memset(&lum, 0, sizeof(lum));
436 lum.handle = channel_data.handle;
437 lum.cmd = LTTNG_UST_CONTEXT;
3b402b40
MD
438 lum.u.context.ctx = LTTNG_UST_CONTEXT_VTID;
439 //lum.u.context.ctx = LTTNG_UST_CONTEXT_PTHREAD_ID;
4847e9bb
MD
440 //lum.u.context.ctx = LTTNG_UST_CONTEXT_VPID;
441 //lum.u.context.ctx = LTTNG_UST_CONTEXT_PROCNAME;
57773204 442 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
8de38cf7
MD
443 if (ret)
444 return ret;
445 context_handle = lur.ret_val;
446 printf("received context handle %u\n", context_handle);
447
b0a99af4
MD
448 /* Get references to channel streams */
449 ret = open_streams(sock, channel_data.handle,
450 stream_data, MAX_NR_STREAMS);
451 if (ret) {
452 printf("Error in open_streams\n");
453 return ret;
454 }
455
456 memset(&lum, 0, sizeof(lum));
457 lum.handle = session_handle;
458 lum.cmd = LTTNG_UST_SESSION_START;
57773204 459 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
460 if (ret)
461 return ret;
462 printf("Session handle %u started.\n", session_handle);
463
464 /* Tell application registration is done */
465 memset(&lum, 0, sizeof(lum));
466 lum.handle = LTTNG_UST_ROOT_HANDLE;
467 lum.cmd = LTTNG_UST_REGISTER_DONE;
57773204 468 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
469 if (ret)
470 return ret;
471 printf("Registration done acknowledged.\n");
472
473 sleep(4);
474
475 ret = consume_buffers(outputpath);
476 if (ret) {
477 printf("Error in consume_buffers\n");
478 return ret;
479 }
480
481 /* Release data channel */
482 /* Release streams */
483 ret = close_streams(sock, stream_data,
484 MAX_NR_STREAMS);
485 if (ret)
486 return ret;
487
8de38cf7
MD
488 /* Release context */
489 memset(&lum, 0, sizeof(lum));
490 lum.handle = context_handle;
491 lum.cmd = LTTNG_UST_RELEASE;
57773204 492 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
8de38cf7
MD
493 if (ret)
494 return ret;
495
b0a99af4
MD
496 /* Release events */
497 for (k = 0; k < nr_events; k++) {
498 memset(&lum, 0, sizeof(lum));
499 lum.handle = event_handle[k];
500 lum.cmd = LTTNG_UST_RELEASE;
57773204 501 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
502 if (ret)
503 return ret;
504 }
505 memset(&lum, 0, sizeof(lum));
506 lum.handle = channel_data.handle;
507 lum.cmd = LTTNG_UST_RELEASE;
57773204 508 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
509 if (ret)
510 return ret;
511 if (channel_data.shm_fd >= 0) {
512 ret = close(channel_data.shm_fd);
513 if (ret)
514 return ret;
515 }
516 if (channel_data.wait_fd >= 0) {
517 ret = close(channel_data.wait_fd);
518 if (ret)
519 return ret;
520 }
521
522 /* Release metadata channel */
523 ret = close_streams(sock, &metadata_stream_data, 1);
524 if (ret)
525 return ret;
526
527 memset(&lum, 0, sizeof(lum));
528 lum.handle = metadata_data.handle;
529 lum.cmd = LTTNG_UST_RELEASE;
57773204 530 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
531 if (ret)
532 return ret;
533 if (metadata_data.shm_fd >= 0) {
534 ret = close(metadata_data.shm_fd);
535 if (ret)
536 return ret;
537 }
538 if (metadata_data.wait_fd >= 0) {
539 ret = close(metadata_data.wait_fd);
540 if (ret)
541 return ret;
542 }
543
544 /* Release session */
545 memset(&lum, 0, sizeof(lum));
546 lum.handle = session_handle;
547 lum.cmd = LTTNG_UST_RELEASE;
57773204 548 ret = ustcomm_send_app_cmd(sock, &lum, &lur);
b0a99af4
MD
549 if (ret)
550 return ret;
551
552 return 0;
553}
554
555/*
556 * Using fork to set umask in the child process (not multi-thread safe). We
557 * deal with the shm_open vs ftruncate race (happening when the sessiond owns
558 * the shm and does not let everybody modify it, to ensure safety against
559 * shm_unlink) by simply letting the mmap fail and retrying after a few
560 * seconds. For global shm, everybody has rw access to it until the sessiond
561 * starts.
562 */
563static int get_wait_shm(char *shm_path, size_t mmap_size, int global)
564{
565 int wait_shm_fd, ret;
566 mode_t mode;
567
568 /* Default permissions */
569 mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
570
571 /* Change owner of the shm path */
572 if (global) {
573 ret = chown(shm_path, 0, 0);
574 if (ret < 0) {
575 if (errno != ENOENT) {
576 perror("chown wait shm");
577 goto error;
578 }
579 }
580
581 /*
582 * If global session daemon, any application can register so the shm
583 * needs to be set in read-only mode for others.
584 */
585 mode |= S_IROTH;
586 } else {
587 ret = chown(shm_path, getuid(), getgid());
588 if (ret < 0) {
589 if (errno != ENOENT) {
590 perror("chown wait shm");
591 goto error;
592 }
593 }
594 }
595
596 /*
597 * Set permissions to the shm even if we did not create the shm.
598 */
599 ret = chmod(shm_path, mode);
600 if (ret < 0) {
601 if (errno != ENOENT) {
602 perror("chmod wait shm");
603 goto error;
604 }
605 }
606
607 /*
608 * We're alone in a child process, so we can modify the process-wide
609 * umask.
610 */
611 umask(~mode);
612
613 /*
614 * Try creating shm (or get rw access). We don't do an exclusive open,
615 * because we allow other processes to create+ftruncate it concurrently.
616 */
617 wait_shm_fd = shm_open(shm_path, O_RDWR | O_CREAT, mode);
618 if (wait_shm_fd < 0) {
619 perror("shm_open wait shm");
620 goto error;
621 }
622
623 ret = ftruncate(wait_shm_fd, mmap_size);
624 if (ret < 0) {
625 perror("ftruncate wait shm");
626 exit(EXIT_FAILURE);
627 }
628
629 ret = fchmod(wait_shm_fd, mode);
630 if (ret < 0) {
631 perror("fchmod");
632 exit(EXIT_FAILURE);
633 }
634
635 printf("Got the wait shm fd %d\n", wait_shm_fd);
636
637 return wait_shm_fd;
638
639error:
640 printf("Failing to get the wait shm fd\n");
641
642 return -1;
643}
644
645int update_futex(int fd, int active)
646{
647 size_t mmap_size = sysconf(_SC_PAGE_SIZE);
648 char *wait_shm_mmap;
649 int ret;
650
651 wait_shm_mmap = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE,
652 MAP_SHARED, fd, 0);
653 if (wait_shm_mmap == MAP_FAILED) {
654 perror("mmap");
655 goto error;
656 }
657
658 if (active) {
659 uatomic_set((int32_t *) wait_shm_mmap, 1);
660 futex_async((int32_t *) wait_shm_mmap, FUTEX_WAKE,
661 INT_MAX, NULL, NULL, 0);
662 } else {
663 uatomic_set((int32_t *) wait_shm_mmap, 0);
664 }
665 ret = munmap(wait_shm_mmap, mmap_size);
666 if (ret) {
667 perror("Error unmapping wait shm");
668 goto error;
669 }
670 return 0;
671error:
672 return -1;
673}
674
675/*
676 * Set open files limit to unlimited. This daemon can open a large number of
677 * file descriptors in order to consumer multiple kernel traces.
678 */
679static void set_ulimit(void)
680{
681 int ret;
682 struct rlimit lim;
683
684 /*
685 * If not root, we cannot increase our max open files. But our
686 * scope is then limited to processes from a single user.
687 */
688 if (getuid() != 0)
689 return;
690 /* The kernel does not allowed an infinite limit for open files */
691 lim.rlim_cur = 65535;
692 lim.rlim_max = 65535;
693
694 ret = setrlimit(RLIMIT_NOFILE, &lim);
695 if (ret < 0) {
696 perror("failed to set open files limit");
697 }
698}
699
700/*
701 * Usage:
702 * ./ust-basic-tracing outputpath event_name1 event_name2 ....
703 */
704int main(int argc, const char **argv)
705{
706 const char *home_dir;
707 int ret, wait_shm_fd;
708 struct sigaction act;
fb50c39d 709 mode_t old_umask = 0;
b0a99af4
MD
710 const char *outputpath;
711 const char **event_names;
712 unsigned int nr_events;
713
714 if (argc < 2) {
715 printf("Usage:\n");
716 printf("%s outputpath event_name1 event_name2 ...\n",
717 argv[0]);
718 exit(-1);
719 }
720 outputpath = argv[1];
721 event_names = &argv[2];
722 nr_events = argc - 2;
723
724 set_ulimit();
725
726 /* Ignore sigpipe */
727 memset(&act, 0, sizeof(act));
728 ret = sigemptyset(&act.sa_mask);
729 if (ret == -1) {
730 perror("sigemptyset");
731 return -1;
732 }
733
734 act.sa_handler = SIG_IGN;
735 ret = sigaction(SIGPIPE, &act, NULL);
736 if (ret == -1) {
737 perror("sigaction");
738 return -1;
739 }
740
741 /* Handle SIGTERM */
742 act.sa_handler = handle_signals;
743 ret = sigaction(SIGTERM, &act, NULL);
744 if (ret == -1) {
745 perror("sigaction");
746 return -1;
747 }
748 /* Handle SIGINT */
749 ret = sigaction(SIGINT, &act, NULL);
750 if (ret == -1) {
751 perror("sigaction");
752 return -1;
753 }
754
755 if (geteuid() == 0) {
756 ret = mkdir(LTTNG_RUNDIR, S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
757 if (ret && errno != EEXIST) {
758 perror("mkdir");
759 return -1;
760 }
761 wait_shm_fd = get_wait_shm(DEFAULT_GLOBAL_APPS_WAIT_SHM_PATH,
762 sysconf(_SC_PAGE_SIZE), 1);
763 if (wait_shm_fd < 0) {
764 perror("global wait shm error");
765 return -1;
766 }
767 strcpy(apps_sock_path, DEFAULT_GLOBAL_APPS_UNIX_SOCK);
768 old_umask = umask(0);
769 } else {
770 snprintf(local_apps_wait_shm_path, PATH_MAX,
771 DEFAULT_HOME_APPS_WAIT_SHM_PATH, getuid());
772 wait_shm_fd = get_wait_shm(local_apps_wait_shm_path,
773 sysconf(_SC_PAGE_SIZE), 0);
774 if (wait_shm_fd < 0) {
775 perror("local wait shm error");
776 return -1;
777 }
778 home_dir = (const char *) getenv("HOME");
779 if (!home_dir) {
780 perror("getenv error");
781 return -ENOENT;
782 }
783 snprintf(apps_sock_path, PATH_MAX,
784 DEFAULT_HOME_APPS_UNIX_SOCK, home_dir);
785 }
786
57773204 787 ret = ustcomm_create_unix_sock(apps_sock_path);
b0a99af4
MD
788 if (ret < 0) {
789 perror("create error");
790 return ret;
791 }
792 apps_socket = ret;
793
794 if (getuid() == 0) {
795 /* File permission MUST be 666 */
796 ret = chmod(apps_sock_path,
797 S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
798 if (ret < 0) {
799 printf("Set file permissions failed: %s\n", apps_sock_path);
800 perror("chmod");
801 goto end;
802 }
803 umask(old_umask);
804 }
57773204 805 ret = ustcomm_listen_unix_sock(apps_socket);
b0a99af4
MD
806 if (ret < 0) {
807 perror("listen error");
808 return ret;
809 }
810
811 /* wake up futexes */
812 ret = update_futex(wait_shm_fd, 1);
813 if (ret) {
814 fprintf(stderr, "Error wakeup futex\n");
815 return -1;
816 }
817
818 for (;;) {
819 int sock;
820 ssize_t len;
821 struct {
822 uint32_t major;
823 uint32_t minor;
824 pid_t pid;
825 pid_t ppid;
826 uid_t uid;
827 gid_t gid;
828 char name[16]; /* Process name */
829 } reg_msg;
830 char bufname[17];
831
832 if (quit_program)
833 break;
834
835 printf("Accepting application registration\n");
57773204 836 sock = ustcomm_accept_unix_sock(apps_socket);
b0a99af4
MD
837 if (sock < 0) {
838 perror("accept error");
839 goto end;
840 }
841
842 /*
843 * Basic recv here to handle the very simple data
844 * that the libust send to register (reg_msg).
845 */
57773204 846 len = ustcomm_recv_unix_sock(sock, &reg_msg, sizeof(reg_msg));
b0a99af4 847 if (len < 0 || len != sizeof(reg_msg)) {
57773204 848 perror("ustcomm_recv_unix_sock");
b0a99af4
MD
849 continue;
850 }
851 memcpy(bufname, reg_msg.name, 16);
852 bufname[16] = '\0';
853 printf("Application %s pid %u ppid %u uid %u gid %u has registered (version : %u.%u)\n",
854 bufname, reg_msg.pid, reg_msg.ppid, reg_msg.uid,
855 reg_msg.gid, reg_msg.major, reg_msg.minor);
856 ret = send_app_msgs(sock, outputpath, nr_events, event_names);
857 if (ret) {
858 printf("Error in send_app_msgs.\n");
859 sleep(1);
860 }
861 close(sock);
862 }
863
864end:
865 printf("quitting.\n");
866 /* Let applications know we are not responding anymore */
867 ret = update_futex(wait_shm_fd, 0);
868 if (ret) {
869 fprintf(stderr, "Error wakeup futex\n");
870 return -1;
871 }
872
873 return 0;
874}
This page took 0.060143 seconds and 4 git commands to generate.