Add parameters name to the function prototype
[lttng-tools.git] / ltt-sessiond / main.c
CommitLineData
826d496d
MD
1/*
2 * Copyright (C) 2011 - David Goulet <david.goulet@polymtl.ca>
fac6795d
DG
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.
91d76f53 8 *
fac6795d
DG
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.
91d76f53 13 *
fac6795d
DG
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.
fac6795d
DG
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) */
5b97ec60 38#include <lttng/lttng.h>
fac6795d
DG
39
40#include "liblttsessiondcomm.h"
41#include "ltt-sessiond.h"
75462a81 42#include "lttngerr.h"
5b74c7b1 43#include "session.h"
fda89c9b 44#include "trace.h"
91d76f53 45#include "traceable-app.h"
fac6795d 46
75462a81 47/* Const values */
686204ab
MD
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
fac6795d 53/* Static functions */
fac6795d 54static int check_existing_daemon(void);
471d1693 55static int ust_connect_app(pid_t pid);
fac6795d 56static int init_daemon_socket(void);
62bd06d8 57static int notify_apps(const char* name);
e065084a
DG
58static int process_client_msg(int sock, struct lttcomm_session_msg*);
59static int send_unix_sock(int sock, void *buf, size_t len);
62bd06d8 60static int set_signal_handler(void);
d6f42150 61static int set_permissions(void);
6abb15de 62static int setup_data_buffer(char **buf, size_t size, struct lttcomm_lttng_header *llh);
d6f42150
DG
63static int create_lttng_rundir(void);
64static int set_kconsumerd_sockets(void);
62bd06d8 65static void cleanup(void);
6abb15de 66static void copy_common_data(struct lttcomm_lttng_header *llh, struct lttcomm_session_msg *lsm);
62bd06d8 67static void sighandler(int sig);
fac6795d 68
1fd70b72
DG
69static void *thread_manage_clients(void *data);
70static void *thread_manage_apps(void *data);
d6f42150 71static void *thread_manage_kconsumerd(void *data);
fac6795d 72
fac6795d 73/* Variables */
62bd06d8
DG
74int opt_verbose;
75int opt_quiet;
fac6795d
DG
76const char *progname;
77const char *opt_tracing_group;
5b8719f5 78static int opt_sig_parent;
fac6795d
DG
79static int opt_daemon;
80static int is_root; /* Set to 1 if the daemon is running as root */
5b8719f5 81static pid_t ppid;
fac6795d 82
d6f42150
DG
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 */
fac6795d 87
d6f42150
DG
88static int client_sock;
89static int apps_sock;
90static int kconsumerd_err_sock;
fac6795d 91
471d1693
DG
92/* Extern in session.h */
93struct ltt_session *current_session;
e065084a 94
d6f42150
DG
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
fac6795d
DG
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;
fac6795d
DG
137
138 /* TODO: Something more elegant is needed but fine for now */
686204ab 139 struct {
fac6795d 140 int reg; /* 1:register, 0:unregister */
686204ab
MD
141 pid_t pid;
142 uid_t uid;
143 } reg_msg;
fac6795d 144
e07ae692
DG
145 DBG("[thread] Manage apps started");
146
fac6795d
DG
147 /* Notify all applications to register */
148 notify_apps(default_global_apps_pipe);
149
d6f42150 150 ret = lttcomm_listen_unix_sock(apps_sock);
fac6795d
DG
151 if (ret < 0) {
152 goto error;
153 }
154
155 while (1) {
156 /* Blocking call, waiting for transmission */
d6f42150 157 sock = lttcomm_accept_unix_sock(apps_sock);
fac6795d
DG
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 */
91d76f53
DG
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 }
fac6795d
DG
181 } else {
182 /* Unregistering */
91d76f53 183 unregister_traceable_app(reg_msg.pid);
fac6795d
DG
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;
fac6795d 202
e07ae692
DG
203 DBG("[thread] Manage client started");
204
d6f42150 205 ret = lttcomm_listen_unix_sock(client_sock);
fac6795d
DG
206 if (ret < 0) {
207 goto error;
208 }
209
5b8719f5
DG
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
fac6795d
DG
217 while (1) {
218 /* Blocking call, waiting for transmission */
d6f42150 219 sock = lttcomm_accept_unix_sock(client_sock);
fac6795d
DG
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));
87378cf5 230 if (ret <= 0) {
fac6795d
DG
231 continue;
232 }
233
234 /* This function dispatch the work to the LTTng or UST libs
e065084a 235 * and then sends back the response to the client. This is needed
6abb15de 236 * because there might be more then one lttcomm_lttng_header to
e065084a 237 * send out so process_client_msg do both jobs.
fac6795d 238 */
e065084a
DG
239 ret = process_client_msg(sock, &lsm);
240 if (ret < 0) {
241 /* Error detected but still accept command */
242 continue;
fac6795d
DG
243 }
244 }
245
246error:
247 return NULL;
248}
249
e065084a
DG
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
fac6795d 267/*
471d1693 268 * ust_connect_app
fac6795d
DG
269 *
270 * Return a socket connected to the libust communication socket
271 * of the application identified by the pid.
379473d2
DG
272 *
273 * If the pid is not found in the traceable list,
274 * return -1 to indicate error.
fac6795d 275 */
471d1693 276static int ust_connect_app(pid_t pid)
fac6795d 277{
91d76f53
DG
278 int sock;
279 struct ltt_traceable_app *lta;
379473d2 280
e07ae692
DG
281 DBG("Connect to application pid %d", pid);
282
91d76f53
DG
283 lta = find_app_by_pid(pid);
284 if (lta == NULL) {
285 /* App not found */
7442b2ba 286 DBG("Application pid %d not found", pid);
379473d2
DG
287 return -1;
288 }
fac6795d 289
91d76f53 290 sock = ustctl_connect_pid(lta->pid);
fac6795d 291 if (sock < 0) {
75462a81 292 ERR("Fail connecting to the PID %d\n", pid);
fac6795d
DG
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
e07ae692
DG
312 DBG("Notify the global application pipe");
313
fac6795d
DG
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
e065084a
DG
330/*
331 * copy_common_data
332 *
6abb15de 333 * Copy common data between lttcomm_lttng_header and lttcomm_session_msg
e065084a 334 */
6abb15de 335static void copy_common_data(struct lttcomm_lttng_header *llh, struct lttcomm_session_msg *lsm)
e065084a 336{
6abb15de
DG
337 llh->cmd_type = lsm->cmd_type;
338 llh->pid = lsm->pid;
aaf97519
DG
339
340 /* Manage uuid */
8028d920 341 if (!uuid_is_null(lsm->session_id)) {
6abb15de 342 uuid_copy(llh->session_id, lsm->session_id);
e065084a 343 }
aaf97519 344
6abb15de
DG
345 strncpy(llh->trace_name, lsm->trace_name, strlen(llh->trace_name));
346 llh->trace_name[strlen(llh->trace_name) - 1] = '\0';
e065084a
DG
347}
348
ca95a216
DG
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 */
6abb15de 357static int setup_data_buffer(char **buf, size_t s_data, struct lttcomm_lttng_header *llh)
ca95a216
DG
358{
359 int ret = 0;
ca95a216
DG
360 size_t buf_size;
361
6abb15de 362 buf_size = sizeof(struct lttcomm_lttng_header) + s_data;
aaf97519
DG
363 *buf = malloc(buf_size);
364 if (*buf == NULL) {
ca95a216
DG
365 perror("malloc");
366 ret = -1;
367 goto error;
368 }
369
6abb15de 370 /* Setup lttcomm_lttng_header data and copy
ca95a216
DG
371 * it to the newly allocated buffer.
372 */
6abb15de
DG
373 llh->payload_size = s_data;
374 memcpy(*buf, llh, sizeof(struct lttcomm_lttng_header));
ca95a216
DG
375
376 return buf_size;
377
378error:
379 return ret;
380}
381
fac6795d
DG
382/*
383 * process_client_msg
384 *
385 * This takes the lttcomm_session_msg struct and process the command requested
e065084a
DG
386 * by the client. It then creates response(s) and send it back to the
387 * given socket (sock).
fac6795d 388 *
e065084a 389 * Return any error encountered or 0 for success.
fac6795d 390 */
e065084a 391static int process_client_msg(int sock, struct lttcomm_session_msg *lsm)
fac6795d 392{
471d1693 393 int ust_sock, ret, buf_size;
7e6e59cd 394 size_t header_size;
aaf97519 395 char *send_buf = NULL;
6abb15de 396 struct lttcomm_lttng_header llh;
fac6795d 397
e07ae692
DG
398 DBG("Processing client message");
399
fac6795d
DG
400 /* Copy common data to identify the response
401 * on the lttng client side.
402 */
6abb15de 403 copy_common_data(&llh, lsm);
fac6795d 404
379473d2
DG
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
fac6795d 417 /* Default return code.
e065084a 418 * In our world, everything is OK... right? ;)
fac6795d 419 */
6abb15de 420 llh.ret_code = LTTCOMM_OK;
fac6795d 421
6abb15de 422 header_size = sizeof(struct lttcomm_lttng_header);
7e6e59cd 423
471d1693
DG
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
fac6795d
DG
434 /* Process by command type */
435 switch (lsm->cmd_type) {
aaf97519
DG
436 case LTTNG_CREATE_SESSION:
437 {
6abb15de 438 ret = create_session(lsm->session_name, &llh.session_id);
aaf97519 439 if (ret < 0) {
27673bb6
DG
440 if (ret == -1) {
441 ret = LTTCOMM_EXIST_SESS;
442 } else {
443 ret = LTTCOMM_FATAL;
444 }
8028d920 445 goto end;
aaf97519
DG
446 }
447
6abb15de 448 buf_size = setup_data_buffer(&send_buf, 0, &llh);
aaf97519
DG
449 if (buf_size < 0) {
450 ret = LTTCOMM_FATAL;
8028d920 451 goto end;
aaf97519
DG
452 }
453
aaf97519
DG
454 break;
455 }
8028d920
DG
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
6abb15de 465 /* No auxiliary data so only send the llh struct. */
8028d920
DG
466 goto end;
467 }
1657e9bb
DG
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,
6abb15de 478 sizeof(struct lttng_trace) * trace_count, &llh);
1657e9bb
DG
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 }
df0da139
DG
487 case UST_CREATE_TRACE:
488 {
471d1693 489 ret = ust_create_trace(ust_sock, lsm->pid);
df0da139 490 if (ret < 0) {
ce3d728c
DG
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;
379473d2 495 goto end;
df0da139
DG
496 }
497
6abb15de 498 /* No auxiliary data so only send the llh struct. */
df0da139
DG
499 goto end;
500 }
fac6795d
DG
501 case UST_LIST_APPS:
502 {
91d76f53 503 unsigned int app_count = get_app_count();
ca95a216 504 /* Stop right now if no apps */
91d76f53 505 if (app_count == 0) {
e065084a 506 ret = LTTCOMM_NO_APPS;
8028d920 507 goto end;
e065084a
DG
508 }
509
ca95a216
DG
510 /* Setup data buffer and details for transmission */
511 buf_size = setup_data_buffer(&send_buf,
6abb15de 512 sizeof(pid_t) * app_count, &llh);
ca95a216
DG
513 if (buf_size < 0) {
514 ret = LTTCOMM_FATAL;
8028d920 515 goto end;
ca95a216
DG
516 }
517
91d76f53 518 get_app_list_pids((pid_t *)(send_buf + header_size));
ca95a216 519
fac6795d
DG
520 break;
521 }
ce3d728c
DG
522 case UST_START_TRACE:
523 {
471d1693 524 ret = ust_start_trace(ust_sock, lsm->pid);
ce3d728c 525
6abb15de 526 /* No auxiliary data so only send the llh struct. */
ce3d728c
DG
527 goto end;
528 }
520ff687
DG
529 case UST_STOP_TRACE:
530 {
471d1693 531 ret = ust_stop_trace(ust_sock, lsm->pid);
520ff687 532
6abb15de 533 /* No auxiliary data so only send the llh struct. */
520ff687
DG
534 goto end;
535 }
57167058
DG
536 case LTTNG_LIST_SESSIONS:
537 {
5b74c7b1 538 unsigned int session_count = get_session_count();
ca95a216
DG
539 /* Stop right now if no session */
540 if (session_count == 0) {
57167058 541 ret = LTTCOMM_NO_SESS;
8028d920 542 goto end;
57167058
DG
543 }
544
ca95a216
DG
545 /* Setup data buffer and details for transmission */
546 buf_size = setup_data_buffer(&send_buf,
6abb15de 547 (sizeof(struct lttng_session) * session_count), &llh);
ca95a216
DG
548 if (buf_size < 0) {
549 ret = LTTCOMM_FATAL;
8028d920 550 goto end;
ca95a216
DG
551 }
552
5b74c7b1 553 get_lttng_session((struct lttng_session *)(send_buf + header_size));
ca95a216 554
57167058
DG
555 break;
556 }
fac6795d 557 default:
e065084a 558 {
fac6795d 559 /* Undefined command */
e065084a 560 ret = LTTCOMM_UND;
8028d920 561 goto end;
e065084a 562 }
fac6795d
DG
563 }
564
1fd70b72
DG
565 ret = send_unix_sock(sock, send_buf, buf_size);
566
ca95a216
DG
567 if (send_buf != NULL) {
568 free(send_buf);
569 }
570
e065084a
DG
571 return ret;
572
8028d920 573end:
7442b2ba 574 DBG("Return code to client %d", ret);
e065084a 575 /* Notify client of error */
6abb15de
DG
576 llh.ret_code = ret;
577 llh.payload_size = 0;
578 send_unix_sock(sock, (void*) &llh, sizeof(llh));
e065084a 579
8028d920 580 return ret;
fac6795d
DG
581}
582
583/*
584 * usage function on stderr
585 */
586static void usage(void)
587{
b716ce68 588 fprintf(stderr, "Usage: %s OPTIONS\n\nOptions:\n", progname);
d6f42150
DG
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");
fac6795d
DG
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' },
d6f42150
DG
612 { "kconsumerd-cmd-sock", 1, 0, 0 },
613 { "kconsumerd-err-sock", 1, 0, 0 },
fac6795d 614 { "daemonize", 0, 0, 'd' },
5b8719f5 615 { "sig-parent", 0, 0, 'S' },
fac6795d
DG
616 { "help", 0, 0, 'h' },
617 { "group", 1, 0, 'g' },
618 { "version", 0, 0, 'V' },
75462a81 619 { "quiet", 0, 0, 'q' },
3f9947db 620 { "verbose", 0, 0, 'v' },
fac6795d
DG
621 { NULL, 0, 0, 0 }
622 };
623
624 while (1) {
625 int option_index = 0;
d6f42150 626 c = getopt_long(argc, argv, "dhqvVS" "a:c:g:s:E:C:", long_options, &option_index);
fac6795d
DG
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;
b716ce68 638 case 'c':
fac6795d
DG
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);
5b8719f5
DG
656 case 'S':
657 opt_sig_parent = 1;
658 break;
d6f42150
DG
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;
75462a81
DG
665 case 'q':
666 opt_quiet = 1;
667 break;
3f9947db
DG
668 case 'v':
669 opt_verbose = 1;
670 break;
fac6795d
DG
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.
d6f42150
DG
685 * apps_sock - The communication socket for all UST apps.
686 * client_sock - The communication of the cli tool (lttng).
fac6795d
DG
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 */
d6f42150
DG
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);
fac6795d
DG
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) {
d6f42150 706 ERR("Set file permissions failed: %s", client_unix_sock_path);
fac6795d
DG
707 perror("chmod");
708 goto end;
709 }
710
711 /* Create the application unix socket */
d6f42150
DG
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);
fac6795d
DG
715 ret = -1;
716 goto end;
717 }
718
d6f42150 719 /* File permission MUST be 666 */
fac6795d
DG
720 ret = chmod(apps_unix_sock_path, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH | S_IWOTH);
721 if (ret < 0) {
d6f42150 722 ERR("Set file permissions failed: %s", apps_unix_sock_path);
fac6795d
DG
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.
62bd06d8 736 * If yes, error is returned.
fac6795d
DG
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/*
62bd06d8 751 * get_home_dir
fac6795d 752 *
62bd06d8
DG
753 * Return pointer to home directory path using
754 * the env variable HOME.
fac6795d 755 *
62bd06d8 756 * Default : /tmp
fac6795d
DG
757 */
758static const char *get_home_dir(void)
759{
760 const char *home_path;
761
686204ab 762 if ((home_path = (const char *) getenv("HOME")) == NULL) {
fac6795d
DG
763 home_path = default_home_dir;
764 }
765
766 return home_path;
767}
768
769/*
d6f42150 770 * set_permissions
fac6795d
DG
771 *
772 * Set the tracing group gid onto the client socket.
773 */
d6f42150 774static int set_permissions(void)
fac6795d
DG
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) {
75462a81 785 ERR("Missing tracing group. Aborting execution.\n");
fac6795d
DG
786 ret = -1;
787 goto end;
788 }
789
d6f42150
DG
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 */
fac6795d
DG
798 ret = chown(client_unix_sock_path, 0, grp->gr_gid);
799 if (ret < 0) {
d6f42150
DG
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);
fac6795d
DG
808 perror("chown");
809 }
810
d6f42150 811 DBG("All permissions are set");
e07ae692 812
fac6795d
DG
813end:
814 return ret;
815}
816
d6f42150
DG
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
fac6795d 881/*
62bd06d8 882 * set_signal_handler
fac6795d 883 *
62bd06d8 884 * Setup signal handler for :
fac6795d
DG
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
e07ae692
DG
916 DBG("Signal handler set for SIGTERM, SIGPIPE and SIGINT");
917
fac6795d
DG
918 return ret;
919}
920
921/**
62bd06d8 922 * sighandler
fac6795d 923 *
62bd06d8 924 * Signal handler for the daemon
fac6795d
DG
925 */
926static void sighandler(int sig)
927{
928 switch (sig) {
929 case SIGPIPE:
e07ae692 930 DBG("SIGPIPE catched");
87378cf5 931 return;
fac6795d 932 case SIGINT:
e07ae692
DG
933 DBG("SIGINT catched");
934 cleanup();
935 break;
fac6795d 936 case SIGTERM:
e07ae692 937 DBG("SIGTERM catched");
fac6795d 938 cleanup();
686204ab 939 break;
fac6795d
DG
940 default:
941 break;
942 }
943
944 exit(EXIT_SUCCESS);
945}
946
947/*
62bd06d8 948 * cleanup
fac6795d 949 *
62bd06d8 950 * Cleanup the daemon on exit
fac6795d
DG
951 */
952static void cleanup()
953{
d6f42150
DG
954 int ret;
955 char *cmd;
956
e07ae692
DG
957 DBG("Cleaning up");
958
fac6795d 959 /* <fun> */
b716ce68
DG
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);
fac6795d
DG
962 /* </fun> */
963
964 unlink(client_unix_sock_path);
965 unlink(apps_unix_sock_path);
d6f42150
DG
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 }
fac6795d
DG
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) {
53094c05
DG
998 ret = daemon(0, 0);
999 if (ret < 0) {
1000 perror("daemon");
1001 goto error;
1002 }
fac6795d
DG
1003 }
1004
1005 /* Check if daemon is UID = 0 */
1006 is_root = !getuid();
1007
1008 /* Set all sockets path */
1009 if (is_root) {
d6f42150
DG
1010 ret = create_lttng_rundir();
1011 if (ret < 0) {
1012 goto error;
1013 }
1014
fac6795d 1015 if (strlen(apps_unix_sock_path) == 0) {
d6f42150
DG
1016 snprintf(apps_unix_sock_path, PATH_MAX,
1017 DEFAULT_GLOBAL_APPS_UNIX_SOCK);
fac6795d
DG
1018 }
1019
1020 if (strlen(client_unix_sock_path) == 0) {
d6f42150
DG
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;
fac6795d
DG
1028 }
1029 } else {
1030 if (strlen(apps_unix_sock_path) == 0) {
d6f42150
DG
1031 snprintf(apps_unix_sock_path, PATH_MAX,
1032 DEFAULT_HOME_APPS_UNIX_SOCK, get_home_dir());
fac6795d
DG
1033 }
1034
1035 /* Set the cli tool unix socket path */
1036 if (strlen(client_unix_sock_path) == 0) {
d6f42150
DG
1037 snprintf(client_unix_sock_path, PATH_MAX,
1038 DEFAULT_HOME_CLIENT_UNIX_SOCK, get_home_dir());
fac6795d
DG
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) {
75462a81 1046 ERR("Already running daemon.\n");
ab118b20 1047 /* We do not goto error because we must not
d6f42150 1048 * cleanup() because a daemon is already running.
ab118b20
DG
1049 */
1050 return EXIT_FAILURE;
fac6795d
DG
1051 }
1052
1053 if (set_signal_handler() < 0) {
1054 goto error;
1055 }
1056
d6f42150 1057 /* Setup the needed unix socket */
fac6795d
DG
1058 if (init_daemon_socket() < 0) {
1059 goto error;
1060 }
1061
1062 /* Set credentials to socket */
d6f42150 1063 if (is_root && (set_permissions() < 0)) {
fac6795d
DG
1064 goto error;
1065 }
1066
5b8719f5
DG
1067 /* Get parent pid if -S, --sig-parent is specified. */
1068 if (opt_sig_parent) {
1069 ppid = getppid();
1070 }
1071
fac6795d
DG
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.073487 seconds and 4 git commands to generate.