liblttd cleanup and error handling fixes
[ltt-control.git] / liblttd / liblttd.c
1 /* liblttd
2 *
3 * Linux Trace Toolkit Daemon
4 *
5 * This is a simple daemon that reads a few relay+debugfs channels and save
6 * them in a trace.
7 *
8 * CPU hot-plugging is supported using inotify.
9 *
10 * Copyright 2005 -
11 * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca>
12 * Copyright 2010 -
13 * Michael Sills-Lavoie <michael.sills-lavoie@polymtl.ca>
14 * Oumarou Dicko <oumarou.dicko@polymtl.ca>
15 *
16 * This library is free software; you can redistribute it and/or
17 * modify it under the terms of the GNU Lesser General Public
18 * License as published by the Free Software Foundation; either
19 * version 2.1 of the License, or (at your option) any later version.
20 *
21 * This library is distributed in the hope that it will be useful,
22 * but WITHOUT ANY WARRANTY; without even the implied warranty of
23 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
24 * Lesser General Public License for more details.
25 *
26 * You should have received a copy of the GNU Lesser General Public
27 * License along with this library; if not, write to the Free Software
28 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
29 */
30
31 #ifdef HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34
35 #include "liblttd.h"
36
37 #define _REENTRANT
38 #define _GNU_SOURCE
39 #include <features.h>
40 #include <stdio.h>
41 #include <unistd.h>
42 #include <errno.h>
43 #include <sys/types.h>
44 #include <stdlib.h>
45 #include <dirent.h>
46 #include <string.h>
47 #include <fcntl.h>
48 #include <sys/stat.h>
49 #include <sys/poll.h>
50 #include <sys/mman.h>
51 #include <sys/syscall.h>
52 #include <unistd.h>
53 #include <asm/ioctls.h>
54
55 #include <linux/version.h>
56
57 /* Relayfs IOCTL */
58 #include <asm/ioctl.h>
59 #include <asm/types.h>
60
61 /* Get the next sub buffer that can be read. */
62 #define RELAY_GET_SB _IOR(0xF5, 0x00,__u32)
63 /* Release the oldest reserved (by "get") sub buffer. */
64 #define RELAY_PUT_SB _IOW(0xF5, 0x01,__u32)
65 /* returns the number of sub buffers in the per cpu channel. */
66 #define RELAY_GET_N_SB _IOR(0xF5, 0x02,__u32)
67 /* returns the size of the current sub buffer. */
68 #define RELAY_GET_SB_SIZE _IOR(0xF5, 0x03, __u32)
69 /* returns the size of data to consume in the current sub-buffer. */
70 #define RELAY_GET_MAX_SB_SIZE _IOR(0xF5, 0x04, __u32)
71
72
73 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,14)
74 #include <sys/inotify.h>
75
76 #define HAS_INOTIFY
77 #else
78 static inline int inotify_init (void)
79 {
80 return -1;
81 }
82
83 static inline int inotify_add_watch (int fd, const char *name, __u32 mask)
84 {
85 return 0;
86 }
87
88 static inline int inotify_rm_watch (int fd, __u32 wd)
89 {
90 return 0;
91 }
92 #undef HAS_INOTIFY
93 #endif
94
95 struct liblttd_thread_data {
96 int thread_num;
97 struct liblttd_instance *instance;
98 };
99
100 #define printf_verbose(fmt, args...) \
101 do { \
102 if (instance->verbose_mode) \
103 printf(fmt, ##args); \
104 } while (0)
105
106
107 int open_buffer_file(struct liblttd_instance *instance, char *filename,
108 char *path_channel, char *base_path_channel)
109 {
110 int open_ret = 0;
111 int ret = 0;
112
113 if (strncmp(filename, "flight-", sizeof("flight-")-1) != 0) {
114 if (instance->dump_flight_only) {
115 printf_verbose("Skipping normal channel %s\n",
116 path_channel);
117 return 0;
118 }
119 } else {
120 if (instance->dump_normal_only) {
121 printf_verbose("Skipping flight channel %s\n",
122 path_channel);
123 return 0;
124 }
125 }
126 printf_verbose("Opening file.\n");
127
128 instance->fd_pairs.pair = realloc(instance->fd_pairs.pair,
129 ++instance->fd_pairs.num_pairs * sizeof(struct fd_pair));
130
131 /* Open the channel in read mode */
132 instance->fd_pairs.pair[instance->fd_pairs.num_pairs-1].channel =
133 open(path_channel, O_RDONLY | O_NONBLOCK);
134 if (instance->fd_pairs.pair[instance->fd_pairs.num_pairs-1].channel == -1) {
135 perror(path_channel);
136 instance->fd_pairs.num_pairs--;
137 return 0; /* continue */
138 }
139
140 if (instance->callbacks->on_open_channel) ret = instance->callbacks->on_open_channel(
141 instance->callbacks, &instance->fd_pairs.pair[instance->fd_pairs.num_pairs-1],
142 base_path_channel);
143
144 if (ret != 0) {
145 open_ret = -1;
146 close(instance->fd_pairs.pair[instance->fd_pairs.num_pairs-1].channel);
147 instance->fd_pairs.num_pairs--;
148 goto end;
149 }
150
151 end:
152 return open_ret;
153 }
154
155 int open_channel_trace_pairs(struct liblttd_instance *instance,
156 char *subchannel_name, char *base_subchannel_name)
157 {
158 DIR *channel_dir = opendir(subchannel_name);
159 struct dirent *entry;
160 struct stat stat_buf;
161 int ret;
162 char path_channel[PATH_MAX];
163 int path_channel_len;
164 char *path_channel_ptr;
165 char *base_subchannel_ptr;
166
167 int open_ret = 0;
168
169 if (channel_dir == NULL) {
170 perror(subchannel_name);
171 open_ret = ENOENT;
172 goto end;
173 }
174
175 printf_verbose("Calling : on new channels folder\n");
176 if (instance->callbacks->on_new_channels_folder) ret = instance->callbacks->
177 on_new_channels_folder(instance->callbacks,
178 base_subchannel_name);
179 if (ret == -1) {
180 open_ret = -1;
181 goto end;
182 }
183
184 strncpy(path_channel, subchannel_name, PATH_MAX-1);
185 path_channel_len = strlen(path_channel);
186 path_channel[path_channel_len] = '/';
187 path_channel_len++;
188 path_channel_ptr = path_channel + path_channel_len;
189 base_subchannel_ptr = path_channel +
190 (base_subchannel_name - subchannel_name);
191
192 #ifdef HAS_INOTIFY
193 instance->inotify_watch_array.elem = realloc(instance->inotify_watch_array.elem,
194 ++instance->inotify_watch_array.num * sizeof(struct inotify_watch));
195
196 printf_verbose("Adding inotify for channel %s\n", path_channel);
197 instance->inotify_watch_array.elem[instance->inotify_watch_array.num-1].wd = inotify_add_watch(instance->inotify_fd, path_channel, IN_CREATE);
198 strcpy(instance->inotify_watch_array.elem[instance->inotify_watch_array.num-1].path_channel, path_channel);
199 instance->inotify_watch_array.elem[instance->inotify_watch_array.num-1].base_path_channel =
200 instance->inotify_watch_array.elem[instance->inotify_watch_array.num-1].path_channel +
201 (base_subchannel_name - subchannel_name);
202 printf_verbose("Added inotify for channel %s, wd %u\n",
203 instance->inotify_watch_array.elem[instance->inotify_watch_array.num-1].path_channel,
204 instance->inotify_watch_array.elem[instance->inotify_watch_array.num-1].wd);
205 #endif
206
207 while((entry = readdir(channel_dir)) != NULL) {
208
209 if (entry->d_name[0] == '.') continue;
210
211 strncpy(path_channel_ptr, entry->d_name, PATH_MAX - path_channel_len);
212
213 ret = stat(path_channel, &stat_buf);
214 if (ret == -1) {
215 perror(path_channel);
216 continue;
217 }
218
219 printf_verbose("Channel file : %s\n", path_channel);
220
221 if (S_ISDIR(stat_buf.st_mode)) {
222
223 printf_verbose("Entering channel subdirectory...\n");
224 ret = open_channel_trace_pairs(instance, path_channel, base_subchannel_ptr);
225 if (ret < 0) continue;
226 } else if (S_ISREG(stat_buf.st_mode)) {
227 open_ret = open_buffer_file(instance, entry->d_name,
228 path_channel, base_subchannel_ptr);
229 if (open_ret)
230 goto end;
231 }
232 }
233
234 end:
235 closedir(channel_dir);
236
237 return open_ret;
238 }
239
240
241 int read_subbuffer(struct liblttd_instance *instance, struct fd_pair *pair)
242 {
243 unsigned int consumed_old, len;
244 int err;
245 long ret;
246 off_t offset;
247
248 err = ioctl(pair->channel, RELAY_GET_SB, &consumed_old);
249 printf_verbose("cookie : %u\n", consumed_old);
250 if (err != 0) {
251 ret = errno;
252 perror("Reserving sub buffer failed (everything is normal, it is due to concurrency)");
253 goto get_error;
254 }
255
256 err = ioctl(pair->channel, RELAY_GET_SB_SIZE, &len);
257 if (err != 0) {
258 ret = errno;
259 perror("Getting sub-buffer len failed.");
260 goto get_error;
261 }
262
263 if (instance->callbacks->on_read_subbuffer)
264 ret = instance->callbacks->on_read_subbuffer(
265 instance->callbacks, pair, len);
266
267 write_error:
268 ret = 0;
269 err = ioctl(pair->channel, RELAY_PUT_SB, &consumed_old);
270 if (err != 0) {
271 ret = errno;
272 if (errno == EFAULT) {
273 perror("Error in unreserving sub buffer\n");
274 } else if (errno == EIO) {
275 /* Should never happen with newer LTTng versions */
276 perror("Reader has been pushed by the writer, last sub-buffer corrupted.");
277 }
278 goto get_error;
279 }
280
281 get_error:
282 return ret;
283 }
284
285
286 int map_channels(struct liblttd_instance *instance, int idx_begin, int idx_end)
287 {
288 int i,j;
289 int ret=0;
290
291 if (instance->fd_pairs.num_pairs <= 0) {
292 printf("No channel to read\n");
293 goto end;
294 }
295
296 /* Get the subbuf sizes and number */
297
298 for(i=idx_begin;i<idx_end;i++) {
299 struct fd_pair *pair = &instance->fd_pairs.pair[i];
300
301 ret = ioctl(pair->channel, RELAY_GET_N_SB, &pair->n_sb);
302 if (ret != 0) {
303 perror("Error in getting the number of sub-buffers");
304 goto end;
305 }
306 ret = ioctl(pair->channel, RELAY_GET_MAX_SB_SIZE,
307 &pair->max_sb_size);
308 if (ret != 0) {
309 perror("Error in getting the max sub-buffer size");
310 goto end;
311 }
312 ret = pthread_mutex_init(&pair->mutex, NULL); /* Fast mutex */
313 if (ret != 0) {
314 perror("Error in mutex init");
315 goto end;
316 }
317 }
318
319 end:
320 return ret;
321 }
322
323 int unmap_channels(struct liblttd_instance *instance)
324 {
325 int j;
326 int ret=0;
327
328 /* Munmap each FD */
329 for(j=0;j<instance->fd_pairs.num_pairs;j++) {
330 struct fd_pair *pair = &instance->fd_pairs.pair[j];
331 int err_ret;
332
333 err_ret = pthread_mutex_destroy(&pair->mutex);
334 if (err_ret != 0) {
335 perror("Error in mutex destroy");
336 }
337 ret |= err_ret;
338 }
339
340 return ret;
341 }
342
343 #ifdef HAS_INOTIFY
344 /* Inotify event arrived.
345 *
346 * Only support add file for now.
347 */
348 int read_inotify(struct liblttd_instance *instance)
349 {
350 char buf[sizeof(struct inotify_event) + PATH_MAX];
351 char path_channel[PATH_MAX];
352 ssize_t len;
353 struct inotify_event *ievent;
354 size_t offset;
355 unsigned int i;
356 int ret;
357 int old_num;
358
359 offset = 0;
360 len = read(instance->inotify_fd, buf, sizeof(struct inotify_event) + PATH_MAX);
361 if (len < 0) {
362
363 if (errno == EAGAIN)
364 return 0; /* another thread got the data before us */
365
366 printf("Error in read from inotify FD %s.\n", strerror(len));
367 return -1;
368 }
369 while(offset < len) {
370 ievent = (struct inotify_event *)&(buf[offset]);
371 for(i=0; i<instance->inotify_watch_array.num; i++) {
372 if (instance->inotify_watch_array.elem[i].wd == ievent->wd &&
373 ievent->mask == IN_CREATE) {
374 printf_verbose(
375 "inotify wd %u event mask : %u for %s%s\n",
376 ievent->wd, ievent->mask,
377 instance->inotify_watch_array.elem[i].path_channel,
378 ievent->name);
379 old_num = instance->fd_pairs.num_pairs;
380 strcpy(path_channel, instance->inotify_watch_array.elem[i].path_channel);
381 strcat(path_channel, ievent->name);
382 if (ret = open_buffer_file(instance, ievent->name, path_channel,
383 path_channel + (instance->inotify_watch_array.elem[i].base_path_channel -
384 instance->inotify_watch_array.elem[i].path_channel))) {
385 printf("Error opening buffer file\n");
386 return -1;
387 }
388 if (ret = map_channels(instance, old_num, instance->fd_pairs.num_pairs)) {
389 printf("Error mapping channel\n");
390 return -1;
391 }
392
393 }
394 }
395 offset += sizeof(*ievent) + ievent->len;
396 }
397 }
398 #endif //HAS_INOTIFY
399
400 /*
401 * read_channels
402 *
403 * Thread worker.
404 *
405 * Read the debugfs channels and write them in the paired tracefiles.
406 *
407 * @fd_pairs : paired channels and trace files.
408 *
409 * returns 0 on success, -1 on error.
410 *
411 * Note that the high priority polled channels are consumed first. We then poll
412 * again to see if these channels are still in priority. Only when no
413 * high priority channel is left, we start reading low priority channels.
414 *
415 * Note that a channel is considered high priority when the buffer is almost
416 * full.
417 */
418
419 int read_channels(struct liblttd_instance *instance, unsigned long thread_num)
420 {
421 struct pollfd *pollfd = NULL;
422 int num_pollfd;
423 int i,j;
424 int num_rdy, num_hup;
425 int high_prio;
426 int ret = 0;
427 int inotify_fds;
428 unsigned int old_num;
429
430 #ifdef HAS_INOTIFY
431 inotify_fds = 1;
432 #else
433 inotify_fds = 0;
434 #endif
435
436 pthread_rwlock_rdlock(&instance->fd_pairs_lock);
437
438 /* Start polling the FD. Keep one fd for inotify */
439 pollfd = malloc((inotify_fds + instance->fd_pairs.num_pairs) * sizeof(struct pollfd));
440
441 #ifdef HAS_INOTIFY
442 pollfd[0].fd = instance->inotify_fd;
443 pollfd[0].events = POLLIN|POLLPRI;
444 #endif
445
446 for(i=0;i<instance->fd_pairs.num_pairs;i++) {
447 pollfd[inotify_fds+i].fd = instance->fd_pairs.pair[i].channel;
448 pollfd[inotify_fds+i].events = POLLIN|POLLPRI;
449 }
450 num_pollfd = inotify_fds + instance->fd_pairs.num_pairs;
451
452
453 pthread_rwlock_unlock(&instance->fd_pairs_lock);
454
455 while(1) {
456 high_prio = 0;
457 num_hup = 0;
458 #ifdef DEBUG
459 printf("Press a key for next poll...\n");
460 char buf[1];
461 read(STDIN_FILENO, &buf, 1);
462 printf("Next poll (polling %d fd) :\n", num_pollfd);
463 #endif //DEBUG
464
465 /* Have we received a signal ? */
466 if (instance->quit_program) break;
467
468 num_rdy = poll(pollfd, num_pollfd, -1);
469
470 if (num_rdy == -1) {
471 perror("Poll error");
472 goto free_fd;
473 }
474
475 printf_verbose("Data received\n");
476 #ifdef HAS_INOTIFY
477 switch(pollfd[0].revents) {
478 case POLLERR:
479 printf_verbose(
480 "Error returned in polling inotify fd %d.\n",
481 pollfd[0].fd);
482 break;
483 case POLLHUP:
484 printf_verbose(
485 "Polling inotify fd %d tells it has hung up.\n",
486 pollfd[0].fd);
487 break;
488 case POLLNVAL:
489 printf_verbose(
490 "Polling inotify fd %d tells fd is not open.\n",
491 pollfd[0].fd);
492 break;
493 case POLLPRI:
494 case POLLIN:
495 printf_verbose(
496 "Polling inotify fd %d : data ready.\n",
497 pollfd[0].fd);
498
499 pthread_rwlock_wrlock(&instance->fd_pairs_lock);
500 read_inotify(instance);
501 pthread_rwlock_unlock(&instance->fd_pairs_lock);
502
503 break;
504 }
505 #endif
506
507 for(i=inotify_fds;i<num_pollfd;i++) {
508 switch(pollfd[i].revents) {
509 case POLLERR:
510 printf_verbose(
511 "Error returned in polling fd %d.\n",
512 pollfd[i].fd);
513 num_hup++;
514 break;
515 case POLLHUP:
516 printf_verbose(
517 "Polling fd %d tells it has hung up.\n",
518 pollfd[i].fd);
519 num_hup++;
520 break;
521 case POLLNVAL:
522 printf_verbose(
523 "Polling fd %d tells fd is not open.\n",
524 pollfd[i].fd);
525 num_hup++;
526 break;
527 case POLLPRI:
528 pthread_rwlock_rdlock(&instance->fd_pairs_lock);
529 if (pthread_mutex_trylock(&instance->fd_pairs.pair[i-inotify_fds].mutex) == 0) {
530 printf_verbose(
531 "Urgent read on fd %d\n",
532 pollfd[i].fd);
533 /* Take care of high priority channels first. */
534 high_prio = 1;
535 /* it's ok to have an unavailable sub-buffer */
536 ret = read_subbuffer(instance, &instance->fd_pairs.pair[i-inotify_fds]);
537 if (ret == EAGAIN) ret = 0;
538
539 ret = pthread_mutex_unlock(&instance->fd_pairs.pair[i-inotify_fds].mutex);
540 if (ret)
541 printf("Error in mutex unlock : %s\n", strerror(ret));
542 }
543 pthread_rwlock_unlock(&instance->fd_pairs_lock);
544 break;
545 }
546 }
547 /* If every buffer FD has hung up, we end the read loop here */
548 if (num_hup == num_pollfd - inotify_fds) break;
549
550 if (!high_prio) {
551 for(i=inotify_fds;i<num_pollfd;i++) {
552 switch(pollfd[i].revents) {
553 case POLLIN:
554 pthread_rwlock_rdlock(&instance->fd_pairs_lock);
555 if (pthread_mutex_trylock(&instance->fd_pairs.pair[i-inotify_fds].mutex) == 0) {
556 /* Take care of low priority channels. */
557 printf_verbose(
558 "Normal read on fd %d\n",
559 pollfd[i].fd);
560 /* it's ok to have an unavailable subbuffer */
561 ret = read_subbuffer(instance, &instance->fd_pairs.pair[i-inotify_fds]);
562 if (ret == EAGAIN) ret = 0;
563
564 ret = pthread_mutex_unlock(&instance->fd_pairs.pair[i-inotify_fds].mutex);
565 if (ret)
566 printf("Error in mutex unlock : %s\n", strerror(ret));
567 }
568 pthread_rwlock_unlock(&instance->fd_pairs_lock);
569 break;
570 }
571 }
572 }
573
574 /* Update pollfd array if an entry was added to fd_pairs */
575 pthread_rwlock_rdlock(&instance->fd_pairs_lock);
576 if ((inotify_fds + instance->fd_pairs.num_pairs) != num_pollfd) {
577 pollfd = realloc(pollfd,
578 (inotify_fds + instance->fd_pairs.num_pairs) * sizeof(struct pollfd));
579 for(i=num_pollfd-inotify_fds;i<instance->fd_pairs.num_pairs;i++) {
580 pollfd[inotify_fds+i].fd = instance->fd_pairs.pair[i].channel;
581 pollfd[inotify_fds+i].events = POLLIN|POLLPRI;
582 }
583 num_pollfd = instance->fd_pairs.num_pairs + inotify_fds;
584 }
585 pthread_rwlock_unlock(&instance->fd_pairs_lock);
586
587 /* NB: If the fd_pairs structure is updated by another thread from this
588 * point forward, the current thread will wait in the poll without
589 * monitoring the new channel. However, this thread will add the
590 * new channel on next poll (and this should not take too much time
591 * on a loaded system).
592 *
593 * This event is quite unlikely and can only occur if a CPU is
594 * hot-plugged while multple lttd threads are running.
595 */
596 }
597
598 free_fd:
599 free(pollfd);
600
601 end:
602 return ret;
603 }
604
605
606 void close_channel_trace_pairs(struct liblttd_instance *instance)
607 {
608 int i;
609 int ret;
610
611 for(i=0;i<instance->fd_pairs.num_pairs;i++) {
612 ret = close(instance->fd_pairs.pair[i].channel);
613 if (ret == -1) perror("Close error on channel");
614 if (instance->callbacks->on_close_channel) {
615 ret = instance->callbacks->on_close_channel(
616 instance->callbacks, &instance->fd_pairs.pair[i]);
617 if (ret != 0) perror("Error on close channel callback");
618 }
619 }
620 free(instance->fd_pairs.pair);
621 free(instance->inotify_watch_array.elem);
622 }
623
624 /* Thread worker */
625 void * thread_main(void *arg)
626 {
627 long ret = 0;
628 struct liblttd_thread_data *thread_data = (struct liblttd_thread_data*) arg;
629
630 if (thread_data->instance->callbacks->on_new_thread)
631 ret = thread_data->instance->callbacks->on_new_thread(
632 thread_data->instance->callbacks, thread_data->thread_num);
633
634 if (ret < 0) {
635 return (void*)ret;
636 }
637 ret = read_channels(thread_data->instance, thread_data->thread_num);
638
639 if (thread_data->instance->callbacks->on_close_thread)
640 thread_data->instance->callbacks->on_close_thread(
641 thread_data->instance->callbacks, thread_data->thread_num);
642
643 free(thread_data);
644
645 return (void*)ret;
646 }
647
648 int channels_init(struct liblttd_instance *instance)
649 {
650 int ret = 0;
651
652 instance->inotify_fd = inotify_init();
653 fcntl(instance->inotify_fd, F_SETFL, O_NONBLOCK);
654
655 if (ret = open_channel_trace_pairs(instance, instance->channel_name,
656 instance->channel_name +
657 strlen(instance->channel_name)))
658 goto close_channel;
659 if (instance->fd_pairs.num_pairs == 0) {
660 printf("No channel available for reading, exiting\n");
661 ret = -ENOENT;
662 goto close_channel;
663 }
664
665 if (ret = map_channels(instance, 0, instance->fd_pairs.num_pairs))
666 goto close_channel;
667 return 0;
668
669 close_channel:
670 close_channel_trace_pairs(instance);
671 if (instance->inotify_fd >= 0)
672 close(instance->inotify_fd);
673 return ret;
674 }
675
676 int delete_instance(struct liblttd_instance *instance)
677 {
678 pthread_rwlock_destroy(&instance->fd_pairs_lock);
679 free(instance);
680 return 0;
681 }
682
683 int liblttd_start_instance(struct liblttd_instance *instance)
684 {
685 int ret = 0;
686 pthread_t *tids;
687 unsigned long i;
688 void *tret;
689
690 if (!instance)
691 return -EINVAL;
692
693 if (ret = channels_init(instance))
694 return ret;
695
696 tids = malloc(sizeof(pthread_t) * instance->num_threads);
697 for(i=0; i<instance->num_threads; i++) {
698 struct liblttd_thread_data *thread_data =
699 malloc(sizeof(struct liblttd_thread_data));
700 thread_data->thread_num = i;
701 thread_data->instance = instance;
702
703 ret = pthread_create(&tids[i], NULL, thread_main, thread_data);
704 if (ret) {
705 perror("Error creating thread");
706 break;
707 }
708 }
709
710 for(i=0; i<instance->num_threads; i++) {
711 ret = pthread_join(tids[i], &tret);
712 if (ret) {
713 perror("Error joining thread");
714 break;
715 }
716 if ((long)tret != 0) {
717 printf("Error %s occured in thread %ld\n",
718 strerror((long)tret), i);
719 }
720 }
721
722 free(tids);
723 ret = unmap_channels(instance);
724 close_channel_trace_pairs(instance);
725 if (instance->inotify_fd >= 0)
726 close(instance->inotify_fd);
727
728 if (instance->callbacks->on_trace_end)
729 instance->callbacks->on_trace_end(instance);
730
731 delete_instance(instance);
732
733 return ret;
734 }
735
736 struct liblttd_instance * liblttd_new_instance(
737 struct liblttd_callbacks *callbacks, char *channel_path,
738 unsigned long n_threads, int flight_only, int normal_only, int verbose)
739 {
740 struct liblttd_instance * instance;
741
742 if (!channel_path || !callbacks)
743 return NULL;
744 if (n_threads == 0)
745 n_threads = 1;
746 if (flight_only && normal_only)
747 return NULL;
748
749 instance = malloc(sizeof(struct liblttd_instance));
750 if (!instance)
751 return NULL;
752
753 instance->callbacks = callbacks;
754
755 instance->inotify_fd = -1;
756
757 instance->fd_pairs.pair = NULL;
758 instance->fd_pairs.num_pairs = 0;
759
760 instance->inotify_watch_array.elem = NULL;
761 instance->inotify_watch_array.num = 0;
762
763 pthread_rwlock_init(&instance->fd_pairs_lock, NULL);
764
765 strncpy(instance->channel_name, channel_path, PATH_MAX -1);
766 instance->num_threads = n_threads;
767 instance->dump_flight_only = flight_only;
768 instance->dump_normal_only = normal_only;
769 instance->verbose_mode = verbose;
770 instance->quit_program = 0;
771
772 return instance;
773 }
774
775 int liblttd_stop_instance(struct liblttd_instance *instance)
776 {
777 instance->quit_program = 1;
778 return 0;
779 }
780
This page took 0.044628 seconds and 4 git commands to generate.