ACLOCAL_AMFLAGS = -I config
-# The order here is tricky. SUBDIRS applies both to compilation and
-# installation. Programs depending on the libs must be built after
-# libust and '.' (that contains the linker script). However, '.'
-# must be installed after libust so it can overwrite libust.so with
-# the linker script.
-SUBDIRS = snprintf liblttng-ust-comm libringbuffer libust include doc tests \
- libustjava
+SUBDIRS = . snprintf liblttng-ust-comm libringbuffer libust include doc tests \
+ libustjava libustfork
#temporarily disabled
-# . libustinstr-malloc libustfork
-
-EXTRA_DIST = libust.ldscript.in libust-initializer.c libust-initializer.h
-
-ldscriptsdir = $(libdir)
-ldscripts_DATA = libust.so libust-initializer.o
-
-CLEANFILES = $(ldscripts_DATA) ./tests/libust-initializer.Po
-
-libust.so: libust.ldscript.in
- $(SED) -e $(if $(LIBFORMAT),"s@\@FORMAT\@@$(LIBFORMAT)@","s@.*\@FORMAT\@.*@@") < $< > $@
-
-# It is very important to compile the initializer with PIC otherwise we
-# may get obscure errors when linking to shared libraries.
-libust-initializer.o: libust-initializer.c
- $(CC) $(CFLAGS) -fno-strict-aliasing -fPIC -c -I$(top_srcdir)/include -I$(top_srcdir) -o $@ $<
+# . libustinstr-malloc
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = ust.pc
ust/lttng-tracer.h \
ust/usterr-signal-safe.h \
ust/core.h \
- ust/share.h
+ ust/share.h \
+ ust/ust.h
# note: usterr-signal-safe.h, core.h and share.h need namespace cleanup.
ust/kcompat/jhash.h \
ust/kcompat/compiler.h \
ust/kcompat/types.h \
- ust/tracectl.h \
ust/stringify.h \
ust/wait.h
+++ /dev/null
-/* Copyright (C) 2009 Pierre-Marc Fournier
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-
-#ifndef UST_TRACECTL_H
-#define UST_TRACECTL_H
-
-typedef struct ust_fork_info {
- sigset_t orig_sigs;
-} ust_fork_info_t;
-
-extern void ust_potential_exec(void);
-
-extern void ust_before_fork(ust_fork_info_t *fork_info);
-extern void ust_after_fork_parent(ust_fork_info_t *fork_info);
-extern void ust_after_fork_child(ust_fork_info_t *fork_info);
-
-#endif /* UST_TRACECTL_H */
+++ /dev/null
-/*
- * Copyright (C) 2009 Novell Inc.
- *
- * Author: Jan Blunck <jblunck@suse.de>
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- */
-
-//DISABLED #include <ust/marker.h>
-#include <ust/tracepoint.h>
-
-//DISABLED UST_MARKER_LIB;
-TRACEPOINT_LIB;
+++ /dev/null
-/* Copyright (C) 2010 Nils Carlson <nils.carlson@ericsson.com>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
- */
-#undef TRACE_SYSTEM
-#define TRACE_SYSTEM ust_dummy
-
-#if !defined(_TRACEPOINT_EVENT_TEST_H) || defined(TRACE_HEADER_MULTI_READ)
-#define _TRACEPOINT_EVENT_TEST_H
-
-#include <ust/tracepoint.h>
-
-TRACEPOINT_EVENT(ust_dummy_event,
-
- TP_PROTO(int dummy_int),
-
- TP_ARGS(dummy_int),
-
- TP_STRUCT__entry(
- __field( int, dummy )
- ),
-
- TP_fast_assign(
- __entry->dummy = dummy_int;
- ),
-
- TP_printf("dummy=%d", __entry->dummy)
-);
-
-#endif /* _TRACEPOINT_EVENT_TEST_H */
-
-/* This part must be outside protection */
-#undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
-#define TRACE_INCLUDE_FILE libust-initializer
-#include <ust/define_trace.h>
+++ /dev/null
-/* GNU ld script
- Use the shared library, but the link with initializer too */
-OUTPUT_FORMAT(@FORMAT@)
-GROUP ( libust.so.0 libust-initializer.o )
#include <semaphore.h>
#include <time.h>
#include <assert.h>
+#include <signal.h>
#include <urcu/uatomic.h>
#include <lttng-ust-comm.h>
#include <ust/lttng-ust-abi.h>
#include <ust/tracepoint.h>
#include <ust/tracepoint-internal.h>
+#include <ust/ust.h>
/*
* Has lttng ust comm constructor been called ?
ltt_ring_buffer_metadata_client_exit();
exit_tracepoint();
}
+
+/*
+ * We exclude the worker threads across fork and clone (except
+ * CLONE_VM), because these system calls only keep the forking thread
+ * running in the child. Therefore, we don't want to call fork or clone
+ * in the middle of an tracepoint or ust tracing state modification.
+ * Holding this mutex protects these structures across fork and clone.
+ */
+void ust_before_fork(ust_fork_info_t *fork_info)
+{
+ /*
+ * Disable signals. This is to avoid that the child intervenes
+ * before it is properly setup for tracing. It is safer to
+ * disable all signals, because then we know we are not breaking
+ * anything by restoring the original mask.
+ */
+ sigset_t all_sigs;
+ int ret;
+
+ /* Disable signals */
+ sigfillset(&all_sigs);
+ ret = sigprocmask(SIG_BLOCK, &all_sigs, &fork_info->orig_sigs);
+ if (ret == -1) {
+ PERROR("sigprocmask");
+ }
+ pthread_mutex_lock(<tng_ust_comm_mutex);
+ rcu_bp_before_fork();
+}
+
+static void ust_after_fork_common(ust_fork_info_t *fork_info)
+{
+ int ret;
+
+ pthread_mutex_unlock(<tng_ust_comm_mutex);
+ /* Restore signals */
+ ret = sigprocmask(SIG_SETMASK, &fork_info->orig_sigs, NULL);
+ if (ret == -1) {
+ PERROR("sigprocmask");
+ }
+}
+
+void ust_after_fork_parent(ust_fork_info_t *fork_info)
+{
+ rcu_bp_after_fork_parent();
+ /* Release mutexes and reenable signals */
+ ust_after_fork_common(fork_info);
+}
+
+void ust_after_fork_child(ust_fork_info_t *fork_info)
+{
+ /* Release urcu mutexes */
+ rcu_bp_after_fork_child();
+ /* Release mutexes and reenable signals */
+ ust_after_fork_common(fork_info);
+}
-/* Copyright (C) 2009 Pierre-Marc Fournier
+/*
+ * Copyright (C) 2009 Pierre-Marc Fournier
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * License as published by the Free Software Foundation; version 2.1 of
+ * the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
#include <signal.h>
#include <sched.h>
#include <stdarg.h>
-#include <ust/tracectl.h>
#include "usterr.h"
+#include <ust/ust.h>
+
struct user_desc;
pid_t fork(void)
{
static pid_t (*plibc_func)(void) = NULL;
ust_fork_info_t fork_info;
-
pid_t retval;
- if(plibc_func == NULL) {
+ if (plibc_func == NULL) {
plibc_func = dlsym(RTLD_NEXT, "fork");
- if(plibc_func == NULL) {
- fprintf(stderr, "libcwrap: unable to find fork\n");
+ if (plibc_func == NULL) {
+ fprintf(stderr, "libustfork: unable to find \"fork\" symbol\n");
return -1;
}
}
ust_before_fork(&fork_info);
-
/* Do the real fork */
retval = plibc_func();
-
- if(retval == 0) {
+ if (retval == 0) {
/* child */
ust_after_fork_child(&fork_info);
- }
- else {
+ } else {
ust_after_fork_parent(&fork_info);
}
-
return retval;
}
-int execve(const char *filename, char *const argv[], char *const envp[])
-{
- static int (*plibc_func)(const char *filename, char *const argv[], char *const envp[]) = NULL;
-
- pid_t retval;
-
- if(plibc_func == NULL) {
- plibc_func = dlsym(RTLD_NEXT, "execve");
- if(plibc_func == NULL) {
- fprintf(stderr, "libinterfork: unable to find execve\n");
- return -1;
- }
- }
-
- ust_potential_exec();
-
- retval = plibc_func(filename, argv, envp);
-
- return retval;
-}
-
-struct interfork_clone_info {
+struct ustfork_clone_info {
int (*fn)(void *);
void *arg;
ust_fork_info_t fork_info;
static int clone_fn(void *arg)
{
- struct interfork_clone_info *info = (struct interfork_clone_info *)arg;
+ struct ustfork_clone_info *info = (struct ustfork_clone_info *) arg;
/* clone is now done and we are in child */
ust_after_fork_child(&info->fork_info);
-
return info->fn(info->arg);
}
int clone(int (*fn)(void *), void *child_stack, int flags, void *arg, ...)
{
- static int (*plibc_func)(int (*fn)(void *), void *child_stack, int flags, void *arg, pid_t *ptid, struct user_desc *tls, pid_t *ctid) = NULL;
-
- /* varargs */
+ static int (*plibc_func)(int (*fn)(void *), void *child_stack,
+ int flags, void *arg, pid_t *ptid,
+ struct user_desc *tls, pid_t *ctid) = NULL;
+ /* var args */
pid_t *ptid;
struct user_desc *tls;
pid_t *ctid;
-
- int retval;
-
+ /* end of var args */
va_list ap;
+ int retval;
va_start(ap, arg);
ptid = va_arg(ap, pid_t *);
ctid = va_arg(ap, pid_t *);
va_end(ap);
- if(plibc_func == NULL) {
+ if (plibc_func == NULL) {
plibc_func = dlsym(RTLD_NEXT, "clone");
- if(plibc_func == NULL) {
- fprintf(stderr, "libinterfork: unable to find clone\n");
+ if (plibc_func == NULL) {
+ fprintf(stderr, "libustfork: unable to find \"clone\" symbol.\n");
return -1;
}
}
- if(flags & CLONE_VM) {
- /* creating a thread, no need to intervene, just pass on the arguments */
- retval = plibc_func(fn, child_stack, flags, arg, ptid, tls, ctid);
- }
- else {
- /* creating a real process, we need to intervene */
- struct interfork_clone_info info = { fn: fn, arg: arg };
+ if (flags & CLONE_VM) {
+ /*
+ * Creating a thread, no need to intervene, just pass on
+ * the arguments.
+ */
+ retval = plibc_func(fn, child_stack, flags, arg, ptid,
+ tls, ctid);
+ } else {
+ /* Creating a real process, we need to intervene. */
+ struct ustfork_clone_info info = { fn: fn, arg: arg };
ust_before_fork(&info.fork_info);
-
- retval = plibc_func(clone_fn, child_stack, flags, &info, ptid, tls, ctid);
-
- /* The child doesn't get here */
+ retval = plibc_func(clone_fn, child_stack, flags, &info,
+ ptid, tls, ctid);
+ /* The child doesn't get here. */
ust_after_fork_parent(&info.fork_info);
}
-
return retval;
}
-SUBDIRS = . hello
-#SUBDIRS = . hello hello2 basic basic_long fork simple_include snprintf test-nevents test-libustinstr-malloc dlopen same_line_marker trace_event register_test tracepoint libustctl_function_tests exit-fast
+SUBDIRS = . hello fork
+#SUBDIRS = . hello2 basic basic_long simple_include snprintf test-nevents test-libustinstr-malloc dlopen same_line_marker trace_event register_test tracepoint libustctl_function_tests exit-fast
dist_noinst_SCRIPTS = test_loop runtests trace_matches
AM_CPPFLAGS = -I$(top_srcdir)/include
noinst_PROGRAMS = fork fork2
-fork_SOURCES = fork.c
-fork_LDADD = $(top_builddir)/libust/libust.la $(top_builddir)/libust-initializer.o
+fork_SOURCES = fork.c ust_tests_fork.h
+fork_LDADD = $(top_builddir)/libust/libust.la
fork2_SOURCES = fork2.c
-fork2_LDADD = $(top_builddir)/libust/libust.la $(top_builddir)/libust-initializer.o
+fork2_LDADD = $(top_builddir)/libust/libust.la
noinst_SCRIPTS = run
EXTRA_DIST = run
-/* Copyright (C) 2009 Pierre-Marc Fournier
+/*
+ * Copyright (C) 2009 Pierre-Marc Fournier
+ * Copyright (C) 2011 Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2.1 of the License, or (at your option) any later version.
+ * License as published by the Free Software Foundation; version 2.1 of
+ * the License.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
#include <sys/types.h>
#include <stdlib.h>
-#include <ust/marker.h>
+#define TRACEPOINT_CREATE_PROBES
+#include "ust_tests_fork.h"
+TRACEPOINT_LIB
int main(int argc, char **argv, char *env[])
{
int result;
- if(argc < 2 ) {
+ if (argc < 2) {
fprintf(stderr, "usage: fork PROG_TO_EXEC\n");
exit(1);
}
printf("Fork test program, parent pid is %d\n", getpid());
- ust_marker(before_fork, UST_MARKER_NOARGS);
-
- /* Sleep here to make sure the consumer is initialized before we fork */
- sleep(1);
+ tracepoint(ust_tests_fork_before_fork);
result = fork();
- if(result == -1) {
+ if (result == -1) {
perror("fork");
return 1;
}
- if(result == 0) {
- char *args[] = {"fork2", NULL};
+ if (result == 0) {
+ char *args[] = { "fork2", NULL };
printf("Child pid is %d\n", getpid());
- ust_marker(after_fork_child, UST_MARKER_NOARGS);
-
- ust_marker(before_exec, "pid %d", getpid());
+ tracepoint(ust_tests_fork_after_fork_child, getpid());
result = execve(argv[1], args, env);
- if(result == -1) {
+ if (result == -1) {
perror("execve");
return 1;
}
-
- ust_marker(after_exec, "pid %d", getpid());
- }
- else {
- ust_marker(after_fork_parent, UST_MARKER_NOARGS);
+ } else {
+ tracepoint(ust_tests_fork_after_fork_parent);
}
return 0;
#include <stdio.h>
#include <unistd.h>
-#include <ust/marker.h>
+#define TRACEPOINT_CREATE_PROBES
+#include "ust_tests_fork.h"
+TRACEPOINT_LIB
int main()
{
printf("IN FORK2\n");
- ust_marker(after_exec, UST_MARKER_NOARGS);
+ tracepoint(ust_tests_fork_after_exec);
return 0;
}
noinst_PROGRAMS = hello
hello_SOURCES = hello.c tp.c tp.h
-hello_LDADD = $(top_builddir)/libust/libust.la \
- $(top_builddir)/libust-initializer.o
+hello_LDADD = $(top_builddir)/libust/libust.la
noinst_SCRIPTS = run
EXTRA_DIST = run
#include <string.h>
#include "ust_tests_hello.h"
+TRACEPOINT_LIB
void inthandler(int sig)
{