Add parameters name to the function prototype
[lttng-tools.git] / ltt-sessiond / main.c
... / ...
CommitLineData
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version 2
7 * of the License, or (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18
19#define _GNU_SOURCE
20#include <fcntl.h>
21#include <getopt.h>
22#include <grp.h>
23#include <limits.h>
24#include <pthread.h>
25#include <signal.h>
26#include <stdio.h>
27#include <stdlib.h>
28#include <string.h>
29#include <sys/ipc.h>
30#include <sys/shm.h>
31#include <sys/socket.h>
32#include <sys/stat.h>
33#include <sys/types.h>
34#include <unistd.h>
35
36#include <urcu/list.h> /* URCU list library (-lurcu) */
37#include <ust/ustctl.h> /* UST control lib (-lust) */
38#include <lttng/lttng.h>
39
40#include "liblttsessiondcomm.h"
41#include "ltt-sessiond.h"
42#include "lttngerr.h"
43#include "session.h"
44#include "trace.h"
45#include "traceable-app.h"
46
47/* Const values */
48const char default_home_dir[] = DEFAULT_HOME_DIR;
49const char default_tracing_group[] = DEFAULT_TRACING_GROUP;
50const char default_ust_sock_dir[] = DEFAULT_UST_SOCK_DIR;
51const char default_global_apps_pipe[] = DEFAULT_GLOBAL_APPS_PIPE;
52
53/* Static functions */
54static int check_existing_daemon(void);
55static int ust_connect_app(pid_t pid);
56static int init_daemon_socket(void);
57static int notify_apps(const char* name);
58static int process_client_msg(int sock, struct lttcomm_session_msg*);
59static int send_unix_sock(int sock, void *buf, size_t len);
60static int set_signal_handler(void);
61static int set_permissions(void);
62static int setup_data_buffer(char **buf, size_t size, struct lttcomm_lttng_header *llh);
63static int create_lttng_rundir(void);
64static int set_kconsumerd_sockets(void);
65static void cleanup(void);
66static void copy_common_data(struct lttcomm_lttng_header *llh, struct lttcomm_session_msg *lsm);
67static void sighandler(int sig);
68
69static void *thread_manage_clients(void *data);
70static void *thread_manage_apps(void *data);
71static void *thread_manage_kconsumerd(void *data);
72
73/* Variables */
74int opt_verbose;
75int opt_quiet;
76const char *progname;
77const char *opt_tracing_group;
78static int opt_sig_parent;
79static int opt_daemon;
80static int is_root; /* Set to 1 if the daemon is running as root */
81static pid_t ppid;
82
83static char apps_unix_sock_path[PATH_MAX]; /* Global application Unix socket path */
84static char client_unix_sock_path[PATH_MAX]; /* Global client Unix socket path */
85static char kconsumerd_err_unix_sock_path[PATH_MAX]; /* kconsumerd error Unix socket path */
86static char kconsumerd_cmd_unix_sock_path[PATH_MAX]; /* kconsumerd command Unix socket path */
87
88static int client_sock;
89static int apps_sock;
90static int kconsumerd_err_sock;
91
92/* Extern in session.h */
93struct ltt_session *current_session;
94
95/*
96 * thread_manage_kconsumerd
97 *
98 * This thread manage the kconsumerd error sent
99 * back to the session daemon.
100 */
101static void *thread_manage_kconsumerd(void *data)
102{
103 int sock, ret;
104
105 DBG("[thread] Manage kconsumerd started");
106
107 ret = lttcomm_listen_unix_sock(kconsumerd_err_sock);
108 if (ret < 0) {
109 goto error;
110 }
111
112 sock = lttcomm_accept_unix_sock(kconsumerd_err_sock);
113 if (sock < 0) {
114 goto error;
115 }
116
117 while (1) {
118 //ret = lttcomm_recv_unix_sock(sock, &lsm, sizeof(lsm));
119 if (ret <= 0) {
120 /* TODO: Consumerd died? */
121 continue;
122 }
123 }
124
125error:
126 return NULL;
127}
128
129/*
130 * thread_manage_apps
131 *
132 * This thread manage the application socket communication
133 */
134static void *thread_manage_apps(void *data)
135{
136 int sock, ret;
137
138 /* TODO: Something more elegant is needed but fine for now */
139 struct {
140 int reg; /* 1:register, 0:unregister */
141 pid_t pid;
142 uid_t uid;
143 } reg_msg;
144
145 DBG("[thread] Manage apps started");
146
147 /* Notify all applications to register */
148 notify_apps(default_global_apps_pipe);
149
150 ret = lttcomm_listen_unix_sock(apps_sock);
151 if (ret < 0) {
152 goto error;
153 }
154
155 while (1) {
156 /* Blocking call, waiting for transmission */
157 sock = lttcomm_accept_unix_sock(apps_sock);
158 if (sock < 0) {
159 goto error;
160 }
161
162 /* Basic recv here to handle the very simple data
163 * that the libust send to register (reg_msg).
164 */
165 ret = recv(sock, &reg_msg, sizeof(reg_msg), 0);
166 if (ret < 0) {
167 perror("recv");
168 continue;
169 }
170
171 /* Add application to the global traceable list */
172 if (reg_msg.reg == 1) {
173 /* Registering */
174 ret = register_traceable_app(reg_msg.pid, reg_msg.uid);
175 if (ret < 0) {
176 /* register_traceable_app only return an error with
177 * ENOMEM. At this point, we better stop everything.
178 */
179 goto error;
180 }
181 } else {
182 /* Unregistering */
183 unregister_traceable_app(reg_msg.pid);
184 }
185 }
186
187error:
188
189 return NULL;
190}
191
192/*
193 * thread_manage_clients
194 *
195 * This thread manage all clients request using the unix
196 * client socket for communication.
197 */
198static void *thread_manage_clients(void *data)
199{
200 int sock, ret;
201 struct lttcomm_session_msg lsm;
202
203 DBG("[thread] Manage client started");
204
205 ret = lttcomm_listen_unix_sock(client_sock);
206 if (ret < 0) {
207 goto error;
208 }
209
210 /* Notify parent pid that we are ready
211 * to accept command for client side.
212 */
213 if (opt_sig_parent) {
214 kill(ppid, SIGCHLD);
215 }
216
217 while (1) {
218 /* Blocking call, waiting for transmission */
219 sock = lttcomm_accept_unix_sock(client_sock);
220 if (sock < 0) {
221 goto error;
222 }
223
224 /*
225 * Data is received from the lttng client. The struct
226 * lttcomm_session_msg (lsm) contains the command and data
227 * request of the client.
228 */
229 ret = lttcomm_recv_unix_sock(sock, &lsm, sizeof(lsm));
230 if (ret <= 0) {
231 continue;
232 }
233
234 /* This function dispatch the work to the LTTng or UST libs
235 * and then sends back the response to the client. This is needed
236 * because there might be more then one lttcomm_lttng_header to
237 * send out so process_client_msg do both jobs.
238 */
239 ret = process_client_msg(sock, &lsm);
240 if (ret < 0) {
241 /* Error detected but still accept command */
242 continue;
243 }
244 }
245
246error:
247 return NULL;
248}
249
250/*
251 * send_unix_sock
252 *
253 * Send data on a unix socket using the liblttsessiondcomm API.
254 *
255 * Return lttcomm error code.
256 */
257static int send_unix_sock(int sock, void *buf, size_t len)
258{
259 /* Check valid length */
260 if (len <= 0) {
261 return -1;
262 }
263
264 return lttcomm_send_unix_sock(sock, buf, len);
265}
266
267/*
268 * ust_connect_app
269 *
270 * Return a socket connected to the libust communication socket
271 * of the application identified by the pid.
272 *
273 * If the pid is not found in the traceable list,
274 * return -1 to indicate error.
275 */
276static int ust_connect_app(pid_t pid)
277{
278 int sock;
279 struct ltt_traceable_app *lta;
280
281 DBG("Connect to application pid %d", pid);
282
283 lta = find_app_by_pid(pid);
284 if (lta == NULL) {
285 /* App not found */
286 DBG("Application pid %d not found", pid);
287 return -1;
288 }
289
290 sock = ustctl_connect_pid(lta->pid);
291 if (sock < 0) {
292 ERR("Fail connecting to the PID %d\n", pid);
293 }
294
295 return sock;
296}
297
298/*
299 * notify_apps
300 *
301 * Notify apps by writing 42 to a named pipe using name.
302 * Every applications waiting for a ltt-sessiond will be notified
303 * and re-register automatically to the session daemon.
304 *
305 * Return open or write error value.
306 */
307static int notify_apps(const char *name)
308{
309 int fd;
310 int ret = -1;
311
312 DBG("Notify the global application pipe");
313
314 /* Try opening the global pipe */
315 fd = open(name, O_WRONLY);
316 if (fd < 0) {
317 goto error;
318 }
319
320 /* Notify by writing on the pipe */
321 ret = write(fd, "42", 2);
322 if (ret < 0) {
323 perror("write");
324 }
325
326error:
327 return ret;
328}
329
330/*
331 * copy_common_data
332 *
333 * Copy common data between lttcomm_lttng_header and lttcomm_session_msg
334 */
335static void copy_common_data(struct lttcomm_lttng_header *llh, struct lttcomm_session_msg *lsm)
336{
337 llh->cmd_type = lsm->cmd_type;
338 llh->pid = lsm->pid;
339
340 /* Manage uuid */
341 if (!uuid_is_null(lsm->session_id)) {
342 uuid_copy(llh->session_id, lsm->session_id);
343 }
344
345 strncpy(llh->trace_name, lsm->trace_name, strlen(llh->trace_name));
346 llh->trace_name[strlen(llh->trace_name) - 1] = '\0';
347}
348
349/*
350 * setup_data_buffer
351 *
352 * Setup the outgoing data buffer for the response
353 * data allocating the right amount of memory.
354 *
355 * Return total size of the buffer pointed by buf.
356 */
357static int setup_data_buffer(char **buf, size_t s_data, struct lttcomm_lttng_header *llh)
358{
359 int ret = 0;
360 size_t buf_size;
361
362 buf_size = sizeof(struct lttcomm_lttng_header) + s_data;
363 *buf = malloc(buf_size);
364 if (*buf == NULL) {
365 perror("malloc");
366 ret = -1;
367 goto error;
368 }
369
370 /* Setup lttcomm_lttng_header data and copy
371 * it to the newly allocated buffer.
372 */
373 llh->payload_size = s_data;
374 memcpy(*buf, llh, sizeof(struct lttcomm_lttng_header));
375
376 return buf_size;
377
378error:
379 return ret;
380}
381
382/*
383 * process_client_msg
384 *
385 * This takes the lttcomm_session_msg struct and process the command requested
386 * by the client. It then creates response(s) and send it back to the
387 * given socket (sock).
388 *
389 * Return any error encountered or 0 for success.
390 */
391static int process_client_msg(int sock, struct lttcomm_session_msg *lsm)
392{
393 int ust_sock, ret, buf_size;
394 size_t header_size;
395 char *send_buf = NULL;
396 struct lttcomm_lttng_header llh;
397
398 DBG("Processing client message");
399
400 /* Copy common data to identify the response
401 * on the lttng client side.
402 */
403 copy_common_data(&llh, lsm);
404
405 /* Check command that needs a session */
406 if (lsm->cmd_type != LTTNG_CREATE_SESSION &&
407 lsm->cmd_type != LTTNG_LIST_SESSIONS &&
408 lsm->cmd_type != UST_LIST_APPS)
409 {
410 current_session = find_session_by_uuid(lsm->session_id);
411 if (current_session == NULL) {
412 ret = LTTCOMM_SELECT_SESS;
413 goto end;
414 }
415 }
416
417 /* Default return code.
418 * In our world, everything is OK... right? ;)
419 */
420 llh.ret_code = LTTCOMM_OK;
421
422 header_size = sizeof(struct lttcomm_lttng_header);
423
424 /* Connect to ust apps if available pid */
425 if (lsm->pid != 0) {
426 /* Connect to app using ustctl API */
427 ust_sock = ust_connect_app(lsm->pid);
428 if (ust_sock < 0) {
429 ret = LTTCOMM_NO_TRACEABLE;
430 goto end;
431 }
432 }
433
434 /* Process by command type */
435 switch (lsm->cmd_type) {
436 case LTTNG_CREATE_SESSION:
437 {
438 ret = create_session(lsm->session_name, &llh.session_id);
439 if (ret < 0) {
440 if (ret == -1) {
441 ret = LTTCOMM_EXIST_SESS;
442 } else {
443 ret = LTTCOMM_FATAL;
444 }
445 goto end;
446 }
447
448 buf_size = setup_data_buffer(&send_buf, 0, &llh);
449 if (buf_size < 0) {
450 ret = LTTCOMM_FATAL;
451 goto end;
452 }
453
454 break;
455 }
456 case LTTNG_DESTROY_SESSION:
457 {
458 ret = destroy_session(&lsm->session_id);
459 if (ret < 0) {
460 ret = LTTCOMM_NO_SESS;
461 } else {
462 ret = LTTCOMM_OK;
463 }
464
465 /* No auxiliary data so only send the llh struct. */
466 goto end;
467 }
468 case LTTNG_LIST_TRACES:
469 {
470 unsigned int trace_count = get_trace_count_per_session(current_session);
471
472 if (trace_count == 0) {
473 ret = LTTCOMM_NO_TRACE;
474 goto end;
475 }
476
477 buf_size = setup_data_buffer(&send_buf,
478 sizeof(struct lttng_trace) * trace_count, &llh);
479 if (buf_size < 0) {
480 ret = LTTCOMM_FATAL;
481 goto end;
482 }
483
484 get_traces_per_session(current_session, (struct lttng_trace *)(send_buf + header_size));
485 break;
486 }
487 case UST_CREATE_TRACE:
488 {
489 ret = ust_create_trace(ust_sock, lsm->pid);
490 if (ret < 0) {
491 /* If -1 is returned from ust_create_trace, malloc
492 * failed so it's pretty much a fatal error.
493 */
494 ret = LTTCOMM_FATAL;
495 goto end;
496 }
497
498 /* No auxiliary data so only send the llh struct. */
499 goto end;
500 }
501 case UST_LIST_APPS:
502 {
503 unsigned int app_count = get_app_count();
504 /* Stop right now if no apps */
505 if (app_count == 0) {
506 ret = LTTCOMM_NO_APPS;
507 goto end;
508 }
509
510 /* Setup data buffer and details for transmission */
511 buf_size = setup_data_buffer(&send_buf,
512 sizeof(pid_t) * app_count, &llh);
513 if (buf_size < 0) {
514 ret = LTTCOMM_FATAL;
515 goto end;
516 }
517
518 get_app_list_pids((pid_t *)(send_buf + header_size));
519
520 break;
521 }
522 case UST_START_TRACE:
523 {
524 ret = ust_start_trace(ust_sock, lsm->pid);
525
526 /* No auxiliary data so only send the llh struct. */
527 goto end;
528 }
529 case UST_STOP_TRACE:
530 {
531 ret = ust_stop_trace(ust_sock, lsm->pid);
532
533 /* No auxiliary data so only send the llh struct. */
534 goto end;
535 }
536 case LTTNG_LIST_SESSIONS:
537 {
538 unsigned int session_count = get_session_count();
539 /* Stop right now if no session */
540 if (session_count == 0) {
541 ret = LTTCOMM_NO_SESS;
542 goto end;
543 }
544
545 /* Setup data buffer and details for transmission */
546 buf_size = setup_data_buffer(&send_buf,
547 (sizeof(struct lttng_session) * session_count), &llh);
548 if (buf_size < 0) {
549 ret = LTTCOMM_FATAL;
550 goto end;
551 }
552
553 get_lttng_session((struct lttng_session *)(send_buf + header_size));
554
555 break;
556 }
557 default:
558 {
559 /* Undefined command */
560 ret = LTTCOMM_UND;
561 goto end;
562 }
563 }
564
565 ret = send_unix_sock(sock, send_buf, buf_size);
566
567 if (send_buf != NULL) {
568 free(send_buf);
569 }
570
571 return ret;
572
573end:
574 DBG("Return code to client %d", ret);
575 /* Notify client of error */
576 llh.ret_code = ret;
577 llh.payload_size = 0;
578 send_unix_sock(sock, (void*) &llh, sizeof(llh));
579
580 return ret;
581}
582
583/*
584 * usage function on stderr
585 */
586static void usage(void)
587{
588 fprintf(stderr, "Usage: %s OPTIONS\n\nOptions:\n", progname);
589 fprintf(stderr, " -h, --help Display this usage.\n");
590 fprintf(stderr, " -c, --client-sock PATH Specify path for the client unix socket\n");
591 fprintf(stderr, " -a, --apps-sock PATH Specify path for apps unix socket\n");
592 fprintf(stderr, " --kconsumerd-err-sock PATH Specify path for the kernel consumer error socket\n");
593 fprintf(stderr, " --kconsumerd-cmd-sock PATH Specify path for the kernel consumer command socket\n");
594 fprintf(stderr, " -d, --daemonize Start as a daemon.\n");
595 fprintf(stderr, " -g, --group NAME Specify the tracing group name. (default: tracing)\n");
596 fprintf(stderr, " -V, --version Show version number.\n");
597 fprintf(stderr, " -S, --sig-parent Send SIGCHLD to parent pid to notify readiness.\n");
598 fprintf(stderr, " -q, --quiet No output at all.\n");
599 fprintf(stderr, " -v, --verbose Verbose mode. Activate DBG() macro.\n");
600}
601
602/*
603 * daemon argument parsing
604 */
605static int parse_args(int argc, char **argv)
606{
607 int c;
608
609 static struct option long_options[] = {
610 { "client-sock", 1, 0, 'c' },
611 { "apps-sock", 1, 0, 'a' },
612 { "kconsumerd-cmd-sock", 1, 0, 0 },
613 { "kconsumerd-err-sock", 1, 0, 0 },
614 { "daemonize", 0, 0, 'd' },
615 { "sig-parent", 0, 0, 'S' },
616 { "help", 0, 0, 'h' },
617 { "group", 1, 0, 'g' },
618 { "version", 0, 0, 'V' },
619 { "quiet", 0, 0, 'q' },
620 { "verbose", 0, 0, 'v' },
621 { NULL, 0, 0, 0 }
622 };
623
624 while (1) {
625 int option_index = 0;
626 c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:E:C:", long_options, &option_index);
627 if (c == -1) {
628 break;
629 }
630
631 switch (c) {
632 case 0:
633 fprintf(stderr, "option %s", long_options[option_index].name);
634 if (optarg) {
635 fprintf(stderr, " with arg %s\n", optarg);
636 }
637 break;
638 case 'c':
639 snprintf(client_unix_sock_path, PATH_MAX, "%s", optarg);
640 break;
641 case 'a':
642 snprintf(apps_unix_sock_path, PATH_MAX, "%s", optarg);
643 break;
644 case 'd':
645 opt_daemon = 1;
646 break;
647 case 'g':
648 opt_tracing_group = strdup(optarg);
649 break;
650 case 'h':
651 usage();
652 exit(EXIT_FAILURE);
653 case 'V':
654 fprintf(stdout, "%s\n", VERSION);
655 exit(EXIT_SUCCESS);
656 case 'S':
657 opt_sig_parent = 1;
658 break;
659 case 'E':
660 snprintf(kconsumerd_err_unix_sock_path, PATH_MAX, "%s", optarg);
661 break;
662 case 'C':
663 snprintf(kconsumerd_cmd_unix_sock_path, PATH_MAX, "%s", optarg);
664 break;
665 case 'q':
666 opt_quiet = 1;
667 break;
668 case 'v':
669 opt_verbose = 1;
670 break;
671 default:
672 /* Unknown option or other error.
673 * Error is printed by getopt, just return */
674 return -1;
675 }
676 }
677
678 return 0;
679}
680
681/*
682 * init_daemon_socket
683 *
684 * Creates the two needed socket by the daemon.
685 * apps_sock - The communication socket for all UST apps.
686 * client_sock - The communication of the cli tool (lttng).
687 */
688static int init_daemon_socket()
689{
690 int ret = 0;
691 mode_t old_umask;
692
693 old_umask = umask(0);
694
695 /* Create client tool unix socket */
696 client_sock = lttcomm_create_unix_sock(client_unix_sock_path);
697 if (client_sock < 0) {
698 ERR("Create unix sock failed: %s", client_unix_sock_path);
699 ret = -1;
700 goto end;
701 }
702
703 /* File permission MUST be 660 */
704 ret = chmod(client_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
705 if (ret < 0) {
706 ERR("Set file permissions failed: %s", client_unix_sock_path);
707 perror("chmod");
708 goto end;
709 }
710
711 /* Create the application unix socket */
712 apps_sock = lttcomm_create_unix_sock(apps_unix_sock_path);
713 if (apps_sock < 0) {
714 ERR("Create unix sock failed: %s", apps_unix_sock_path);
715 ret = -1;
716 goto end;
717 }
718
719 /* File permission MUST be 666 */
720 ret = chmod(apps_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
721 if (ret < 0) {
722 ERR("Set file permissions failed: %s", apps_unix_sock_path);
723 perror("chmod");
724 goto end;
725 }
726
727end:
728 umask(old_umask);
729 return ret;
730}
731
732/*
733 * check_existing_daemon
734 *
735 * Check if the global socket is available.
736 * If yes, error is returned.
737 */
738static int check_existing_daemon()
739{
740 int ret;
741
742 ret = access(client_unix_sock_path, F_OK);
743 if (ret == 0) {
744 ret = access(apps_unix_sock_path, F_OK);
745 }
746
747 return ret;
748}
749
750/*
751 * get_home_dir
752 *
753 * Return pointer to home directory path using
754 * the env variable HOME.
755 *
756 * Default : /tmp
757 */
758static const char *get_home_dir(void)
759{
760 const char *home_path;
761
762 if ((home_path = (const char *) getenv("HOME")) == NULL) {
763 home_path = default_home_dir;
764 }
765
766 return home_path;
767}
768
769/*
770 * set_permissions
771 *
772 * Set the tracing group gid onto the client socket.
773 */
774static int set_permissions(void)
775{
776 int ret;
777 struct group *grp;
778
779 /* Decide which group name to use */
780 (opt_tracing_group != NULL) ?
781 (grp = getgrnam(opt_tracing_group)) :
782 (grp = getgrnam(default_tracing_group));
783
784 if (grp == NULL) {
785 ERR("Missing tracing group. Aborting execution.\n");
786 ret = -1;
787 goto end;
788 }
789
790 /* Set lttng run dir */
791 ret = chown(LTTNG_RUNDIR, 0, grp->gr_gid);
792 if (ret < 0) {
793 ERR("Unable to set group on " LTTNG_RUNDIR);
794 perror("chown");
795 }
796
797 /* lttng client socket path */
798 ret = chown(client_unix_sock_path, 0, grp->gr_gid);
799 if (ret < 0) {
800 ERR("Unable to set group on %s", client_unix_sock_path);
801 perror("chown");
802 }
803
804 /* kconsumerd error socket path */
805 ret = chown(kconsumerd_err_unix_sock_path, 0, grp->gr_gid);
806 if (ret < 0) {
807 ERR("Unable to set group on %s", kconsumerd_err_unix_sock_path);
808 perror("chown");
809 }
810
811 DBG("All permissions are set");
812
813end:
814 return ret;
815}
816
817/*
818 * create_lttng_rundir
819 *
820 * Create the lttng run directory needed for all
821 * global sockets and pipe.
822 */
823static int create_lttng_rundir(void)
824{
825 int ret;
826
827 ret = mkdir(LTTNG_RUNDIR, S_IRWXU | S_IRWXG );
828 if (ret < 0) {
829 ERR("Unable to create " LTTNG_RUNDIR);
830 goto error;
831 }
832
833error:
834 return ret;
835}
836
837/*
838 * set_kconsumerd_sockets
839 *
840 * Setup sockets and directory needed by the kconsumerd
841 * communication with the session daemon.
842 */
843static int set_kconsumerd_sockets(void)
844{
845 int ret;
846
847 if (strlen(kconsumerd_err_unix_sock_path) == 0) {
848 snprintf(kconsumerd_err_unix_sock_path, PATH_MAX, KCONSUMERD_ERR_SOCK_PATH);
849 }
850
851 if (strlen(kconsumerd_cmd_unix_sock_path) == 0) {
852 snprintf(kconsumerd_cmd_unix_sock_path, PATH_MAX, KCONSUMERD_CMD_SOCK_PATH);
853 }
854
855 ret = mkdir(KCONSUMERD_PATH, S_IRWXU | S_IRWXG);
856 if (ret < 0) {
857 ERR("Failed to create " KCONSUMERD_PATH);
858 goto error;
859 }
860
861 /* Create the kconsumerd error unix socket */
862 kconsumerd_err_sock = lttcomm_create_unix_sock(kconsumerd_err_unix_sock_path);
863 if (kconsumerd_err_sock < 0) {
864 ERR("Create unix sock failed: %s", kconsumerd_err_unix_sock_path);
865 ret = -1;
866 goto error;
867 }
868
869 /* File permission MUST be 660 */
870 ret = chmod(kconsumerd_err_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
871 if (ret < 0) {
872 ERR("Set file permissions failed: %s", kconsumerd_err_unix_sock_path);
873 perror("chmod");
874 goto error;
875 }
876
877error:
878 return ret;
879}
880
881/*
882 * set_signal_handler
883 *
884 * Setup signal handler for :
885 * SIGINT, SIGTERM, SIGPIPE
886 */
887static int set_signal_handler(void)
888{
889 int ret = 0;
890 struct sigaction sa;
891 sigset_t sigset;
892
893 if ((ret = sigemptyset(&sigset)) < 0) {
894 perror("sigemptyset");
895 return ret;
896 }
897
898 sa.sa_handler = sighandler;
899 sa.sa_mask = sigset;
900 sa.sa_flags = 0;
901 if ((ret = sigaction(SIGTERM, &sa, NULL)) < 0) {
902 perror("sigaction");
903 return ret;
904 }
905
906 if ((ret = sigaction(SIGINT, &sa, NULL)) < 0) {
907 perror("sigaction");
908 return ret;
909 }
910
911 if ((ret = sigaction(SIGPIPE, &sa, NULL)) < 0) {
912 perror("sigaction");
913 return ret;
914 }
915
916 DBG("Signal handler set for SIGTERM, SIGPIPE and SIGINT");
917
918 return ret;
919}
920
921/**
922 * sighandler
923 *
924 * Signal handler for the daemon
925 */
926static void sighandler(int sig)
927{
928 switch (sig) {
929 case SIGPIPE:
930 DBG("SIGPIPE catched");
931 return;
932 case SIGINT:
933 DBG("SIGINT catched");
934 cleanup();
935 break;
936 case SIGTERM:
937 DBG("SIGTERM catched");
938 cleanup();
939 break;
940 default:
941 break;
942 }
943
944 exit(EXIT_SUCCESS);
945}
946
947/*
948 * cleanup
949 *
950 * Cleanup the daemon on exit
951 */
952static void cleanup()
953{
954 int ret;
955 char *cmd;
956
957 DBG("Cleaning up");
958
959 /* <fun> */
960 MSG("\n%c[%d;%dm*** assert failed *** ==> %c[%dm", 27,1,31,27,0);
961 MSG("%c[%d;%dmMatthew, BEET driven development works!%c[%dm",27,1,33,27,0);
962 /* </fun> */
963
964 unlink(client_unix_sock_path);
965 unlink(apps_unix_sock_path);
966 unlink(kconsumerd_err_unix_sock_path);
967
968 ret = asprintf(&cmd, "rm -rf " LTTNG_RUNDIR);
969 if (ret < 0) {
970 ERR("asprintf failed. Something is really wrong!");
971 }
972
973 /* Remove lttng run directory */
974 ret = system(cmd);
975 if (ret < 0) {
976 ERR("Unable to clean " LTTNG_RUNDIR);
977 }
978}
979
980/*
981 * main
982 */
983int main(int argc, char **argv)
984{
985 int i;
986 int ret = 0;
987 void *status;
988 pthread_t threads[2];
989
990 /* Parse arguments */
991 progname = argv[0];
992 if ((ret = parse_args(argc, argv) < 0)) {
993 goto error;
994 }
995
996 /* Daemonize */
997 if (opt_daemon) {
998 ret = daemon(0, 0);
999 if (ret < 0) {
1000 perror("daemon");
1001 goto error;
1002 }
1003 }
1004
1005 /* Check if daemon is UID = 0 */
1006 is_root = !getuid();
1007
1008 /* Set all sockets path */
1009 if (is_root) {
1010 ret = create_lttng_rundir();
1011 if (ret < 0) {
1012 goto error;
1013 }
1014
1015 if (strlen(apps_unix_sock_path) == 0) {
1016 snprintf(apps_unix_sock_path, PATH_MAX,
1017 DEFAULT_GLOBAL_APPS_UNIX_SOCK);
1018 }
1019
1020 if (strlen(client_unix_sock_path) == 0) {
1021 snprintf(client_unix_sock_path, PATH_MAX,
1022 DEFAULT_GLOBAL_CLIENT_UNIX_SOCK);
1023 }
1024
1025 ret = set_kconsumerd_sockets();
1026 if (ret < 0) {
1027 goto error;
1028 }
1029 } else {
1030 if (strlen(apps_unix_sock_path) == 0) {
1031 snprintf(apps_unix_sock_path, PATH_MAX,
1032 DEFAULT_HOME_APPS_UNIX_SOCK, get_home_dir());
1033 }
1034
1035 /* Set the cli tool unix socket path */
1036 if (strlen(client_unix_sock_path) == 0) {
1037 snprintf(client_unix_sock_path, PATH_MAX,
1038 DEFAULT_HOME_CLIENT_UNIX_SOCK, get_home_dir());
1039 }
1040 }
1041
1042 /* See if daemon already exist. If any of the two
1043 * socket needed by the daemon are present, this test fails
1044 */
1045 if ((ret = check_existing_daemon()) == 0) {
1046 ERR("Already running daemon.\n");
1047 /* We do not goto error because we must not
1048 * cleanup() because a daemon is already running.
1049 */
1050 return EXIT_FAILURE;
1051 }
1052
1053 if (set_signal_handler() < 0) {
1054 goto error;
1055 }
1056
1057 /* Setup the needed unix socket */
1058 if (init_daemon_socket() < 0) {
1059 goto error;
1060 }
1061
1062 /* Set credentials to socket */
1063 if (is_root && (set_permissions() < 0)) {
1064 goto error;
1065 }
1066
1067 /* Get parent pid if -S, --sig-parent is specified. */
1068 if (opt_sig_parent) {
1069 ppid = getppid();
1070 }
1071
1072 while (1) {
1073 /* Create thread to manage the client socket */
1074 ret = pthread_create(&threads[0], NULL, thread_manage_clients, (void *) NULL);
1075 if (ret != 0) {
1076 perror("pthread_create");
1077 goto error;
1078 }
1079
1080 /* Create thread to manage application socket */
1081 ret = pthread_create(&threads[1], NULL, thread_manage_apps, (void *) NULL);
1082 if (ret != 0) {
1083 perror("pthread_create");
1084 goto error;
1085 }
1086
1087 for (i = 0; i < 2; i++) {
1088 ret = pthread_join(threads[i], &status);
1089 if (ret != 0) {
1090 perror("pthread_join");
1091 goto error;
1092 }
1093 }
1094 }
1095
1096 cleanup();
1097 return 0;
1098
1099error:
1100 cleanup();
1101
1102 return EXIT_FAILURE;
1103}
This page took 0.025378 seconds and 4 git commands to generate.