X-Git-Url: http://git.lttng.org/?p=ust.git;a=blobdiff_plain;f=usttrace;h=d1a6e5fef71b1c3ee6db7c609557e8ae640a83ae;hp=52c378dfbd12041636f1630e7b82d49ee51bcbb6;hb=HEAD;hpb=2b3c64a412053525cff6233a963f37f4bfbdb284 diff --git a/usttrace b/usttrace index 52c378d..d1a6e5f 100755 --- a/usttrace +++ b/usttrace @@ -1,40 +1,75 @@ -#!/bin/bash +#!/bin/sh # usttrace by Pierre-Marc Fournier 2009 # Distributed under the GPLv2. -USTTRACE_DIR="$(dirname $0)" -USTD="${USTTRACE_DIR}/ustd/ustd" -LIBINTERFORK_PATH="${USTTRACE_DIR}/libinterfork/.libs/libinterfork.so" -LIBMALLOCWRAP_PATH="${USTTRACE_DIR}/libmallocwrap/.libs/libmallocwrap.so" +error() { + echo "$0: error: $1" 1>&2 +} -STD_LDLIBRARY_UST="${USTTRACE_DIR}/libust/.libs" +sighandler() { + echo "Caught Ctrl-C" + if [ -z "${UST_CONSUMERD_PID}" ]; then + UST_CONSUMERD_PID=`cat $pidfilepath` + fi + # Tell the daemon to die + kill -TERM "${UST_CONSUMERD_PID}" -BASE_TRACE_DIR="${HOME}/.usttraces" + echo "Waiting for ust-consumerd to shutdown..." + wait "${UST_CONSUMERD_PID}" -function usage () { - echo "usage: $0 OPTIONS COMMAND" 2>/dev/stderr - echo "" 2>/dev/stderr - echo "Options:" 2>/dev/stderr - echo " -l Runtime link with UST library." 2>/dev/stderr - echo " (Needed only if program was not linked at compile time with libust.)" 2>/dev/stderr - echo " -L Add path to ust libraries to LD_LIBRARY_PATH." 2>/dev/stderr - echo " -m Instrument malloc calls." 2>/dev/stderr - echo " -f Also trace forked processes." 2>/dev/stderr - echo " -s Use system-wide daemon instead of creating one for this session." 2>/dev/stderr + rm "$pidfilepath" + + exit 0; } -function error() { - echo "$0: error: $1" 2>/dev/stderr +USTTRACE_DIR="$(dirname $0)" +if [ -x "${USTTRACE_DIR}/ust-consumerd/ust-consumerd" ] ; then + # Use the not installed libraries instead + UST_CONSUMERD="${USTTRACE_DIR}/ust-consumerd/ust-consumerd" + LIBINTERFORK_PATH="${USTTRACE_DIR}/libustfork/.libs/libustfork.so" + LIBMALLOCWRAP_PATH="${USTTRACE_DIR}/libustinstr-malloc/.libs/libustinstr-malloc.so" + LIBUST_PATH="${USTTRACE_DIR}/libust/.libs/libust.so" +else + # Use the libraries that the dynamic link finds + UST_CONSUMERD="ust-consumerd" + if [ ! -x "$(which ust-consumerd 2>/dev/null)" ]; then + error "cannot find an executable ust-consumerd; make sure its location is in the PATH" + exit 1 + fi + LIBINTERFORK_PATH="libustfork.so" + LIBMALLOCWRAP_PATH="libustinstr-malloc.so" + LIBUST_PATH="libust.so.0" +fi + +BASE_TRACE_DIR="${HOME}/.usttraces" + +usage() { + echo "usage: $0 OPTIONS COMMAND" 1>&2 + echo "" 1>&2 + echo "Options:" 1>&2 + echo " -l Runtime link with UST library." 1>&2 + echo " (Needed only if program was not linked at compile time with libust.)" 1>&2 + echo " -L Add path to ust libraries to LD_LIBRARY_PATH." 1>&2 + echo " -m Instrument malloc calls." 1>&2 + echo " -f Also trace forked processes." 1>&2 + echo " -s Use system-wide daemon instead of creating one for this session." 1>&2 + echo " -S Specify the subbuffer size." 1>&2 + echo " -N Specify the number of subbuffers." 1>&2 + echo " -o Output directory of the trace." 1>&2 } -while getopts ":hlLmfs" options; do +while getopts ":hlLmfsWS:N:o:" options; do case $options in l) arg_preload_libust=1;; L) arg_ld_std_ust=1;; m) arg_preload_malloc=1;; f) arg_preload_fork=1;; s) arg_syswide_daemon=1;; + W) where=1;; + S) export UST_SUBBUF_SIZE=$OPTARG;; + N) export UST_SUBBUF_NUM=$OPTARG;; + o) OUTPUT_DIR=$OPTARG;; h) usage; exit 0;; \?) usage @@ -45,22 +80,18 @@ while getopts ":hlLmfs" options; do done shift $(($OPTIND - 1)) -if [ ! -x "$USTD" ]; -then - error "specified path to ustd not executable ($USTD)" - exit 1 +if [ -n "$where" ]; then + echo $BASE_TRACE_DIR/$(ls "$BASE_TRACE_DIR" | tail -n 1) + exit 0 fi -# Prepare vars -CMD=$1 - # Validate input if [ -z "$HOME" ]; then error "no home specified" fi -if [ -z "$CMD" ]; +if [ -z "$*" ]; then error "no command specified" usage; @@ -68,56 +99,102 @@ then fi # Create directory for trace output -DATESTRING="$(hostname)-$(date +%Y%m%d%H%M%S)" -OUTDIR="$BASE_TRACE_DIR/$DATESTRING" -mkdir -p "$OUTDIR" +if [ -n "$OUTPUT_DIR" ]; then + OUTDIR=$OUTPUT_DIR +else + DATESTRING="$(hostname)-$(date +%Y%m%d%H%M%S%N)" + OUTDIR="$BASE_TRACE_DIR/$DATESTRING" +fi -# Choose socket path -SOCKPATH="/tmp/ust-sock-$$" +# Check if directory exist +if [ ! -d "$OUTDIR" ]; then + mkdir -p $OUTDIR + if [ $? -eq 1 ]; then + exit 1 + fi +fi + +# Choose ust-consumerd socket path +UST_CONSUMERD_SOCKPATH="/tmp/ust-consumerd-sock-$$" if [ "$arg_syswide_daemon" != "1" ]; then - pidfilepath="/tmp/usttrace-$USER-$(date +%Y%m%d%H%M%S%N)-ustd-pid" + pidfilepath="/tmp/usttrace-$USER-$(date +%Y%m%d%H%M%S%N)-ust-consumerd-pid" + trap "sighandler $pidfilepath" INT mkfifo -m 0600 "$pidfilepath" # Start daemon - $USTD --pidfile "$pidfilepath" -s "$SOCKPATH" -o "$OUTDIR" >"$OUTDIR/ustd.log" 2>&1 & - USTDPID="$(<$pidfilepath)" - export UST_DAEMON_SOCKET="$SOCKPATH" + ${UST_CONSUMERD} --pidfile "$pidfilepath" -s "${UST_CONSUMERD_SOCKPATH}" -o "$OUTDIR" >"$OUTDIR/ust-consumerd.log" 2>&1 & + # ust-consumerd sets up its server socket + # ust-consumerd opens the pidfile, blocks because no one has opened it + # we open pidfile + # we block reading pidfile + # ust-consumerd writes to pidfile + # ust-consumerd closes pidfile + # we unblock reading pidfile + UST_CONSUMERD_PID=`cat $pidfilepath` + export UST_DAEMON_SOCKET="${UST_CONSUMERD_SOCKPATH}" fi # Establish the environment for the command -export UST_TRACE=1 -export UST_AUTOPROBE=1 - -if [ "$arg_preload_libust" = "1" ]; -then - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:./libust/.libs" - export LD_PRELOAD="$LD_PRELOAD:./libust/.libs/libust.so" -fi - -if [ "$arg_ld_std_ust" = "1" ]; -then - export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:$STD_LDLIBRARY_UST" -fi - -if [ "$arg_preload_malloc" = "1" ]; -then - export LD_PRELOAD="$LD_PRELOAD:./libmallocwrap/.libs/libmallocwrap.so" -fi - -if [ "$arg_preload_fork" = "1" ]; -then - export LD_PRELOAD="$LD_PRELOAD:$LIBINTERFORK_PATH" -fi - -# Install a handler for SIGIO. This is the signal that will be sent by ustd to -# the traced program to trigger the creation of its listener thread. However, -# it is possible that the SIGIO will be sent after the shell fork, but before -# the exec of the command. If this handler isn't there, bash might terminate -# because of a unhandled signal. +( + export UST_TRACE=1 + export UST_AUTOPROBE=1 + + if [ "$arg_preload_libust" = "1" ]; + then + if [ -n "${LIBUST_PATH%libust.so}" ]; + then + if [ -n "$LD_LIBRARY_PATH" ]; + then + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${LIBUST_PATH%libust.so}" + else + export LD_LIBRARY_PATH="${LIBUST_PATH%libust.so}" + fi + fi + if [ -n "$LIBUST_PATH" ]; + then + if [ -n "$LD_PRELOAD" ]; + then + export LD_PRELOAD="$LD_PRELOAD:$LIBUST_PATH" + else + export LD_PRELOAD="$LIBUST_PATH" + fi + fi + fi + + if [ "$arg_ld_std_ust" = "1" ] && [ -n "${LIBUST_PATH%libust.so}" ]; + then + if [ -n "$LD_LIBRARY_PATH" ]; + then + export LD_LIBRARY_PATH="$LD_LIBRARY_PATH:${LIBUST_PATH%libust.so}" + else + export LD_LIBRARY_PATH="${LIBUST_PATH%libust.so}" + fi + fi + + if [ "$arg_preload_malloc" = "1" ] && [ -n "$LIBMALLOCWRAP_PATH" ]; + then + if [ -n "$LD_PRELOAD" ]; + then + export LD_PRELOAD="$LD_PRELOAD:$LIBMALLOCWRAP_PATH" + else + export LD_PRELOAD="$LIBMALLOCWRAP_PATH" + fi + fi + + if [ "$arg_preload_fork" = "1" ] && [ -n "$LIBINTERFORK_PATH" ]; + then + if [ -n "$LD_PRELOAD" ]; + then + export LD_PRELOAD="$LD_PRELOAD:$LIBINTERFORK_PATH" + else + export LD_PRELOAD="$LIBINTERFORK_PATH" + fi + fi # Execute the command -bash -c "$CMD" 2>&1 | tee "$OUTDIR/app.log" + "$@" 2>&1 +) | tee "$OUTDIR/app.log" ## Because of the keepalive mechanism, we're sure that by the time ## we get here, the daemon is connected to all the buffers that still exist. @@ -126,10 +203,10 @@ bash -c "$CMD" 2>&1 | tee "$OUTDIR/app.log" if [ "$arg_syswide_daemon" != "1" ]; then # Tell the daemon to die - kill -SIGTERM "$USTDPID" + kill -TERM "${UST_CONSUMERD_PID}" - echo "Waiting for ustd to shutdown..." - wait "$(USTDPID)" + echo "Waiting for ust-consumerd to shutdown..." + wait "${UST_CONSUMERD_PID}" rm "$pidfilepath" fi