#!/bin/sh
# Helper for MTR: fail the first rename() of mysqld with EIO via strace.
#
#   strace_inject.sh start <pid_file> <trace_file>
#   strace_inject.sh stop  <pid_file> <trace_file>
#
# Needs passwordless sudo (sudo -n) and strace >= 4.22.
# 'start' returns only after strace is really attached (TracerPid != 0),
# so there is no sleep/race. 'stop' returns only after strace has detached.

cmd="$1"; pid_file="$2"; trace="$3"
# Syscalls to trace and fail (first call only). Override with e.g. INJECT_SYSCALLS=unlink
calls="${INJECT_SYSCALLS:-rename,renameat,renameat2}"
# What to inject on the first call: default error=EIO. e.g. INJECT_ACTION=signal=KILL kills mysqld there.
action="${INJECT_ACTION:-error=EIO}"
spid_file="$trace.strace_pid"

mpid=$(cat "$pid_file" 2>/dev/null)
[ -n "$mpid" ] && [ -d "/proc/$mpid" ] || { echo "bad mysqld pid file: $pid_file" >&2; exit 2; }

tracer() { awk '/^TracerPid:/ {print $2}' "/proc/$mpid/status"; }

case "$cmd" in
  start)
    rm -f "$trace" "$spid_file"
    # 'exec' keeps the shell's PID, so $$ is strace's own PID
    nohup sudo -n sh -c "echo \$\$ > '$spid_file'; exec strace -f -qq -y -p $mpid \
        -e trace=$calls \
        -e inject=$calls:$action:when=1 \
        -o '$trace'" >/dev/null 2>&1 &
    i=0
    while [ "$(tracer)" = "0" ] || [ -z "$(tracer)" ]; do
      i=$((i+1)); [ $i -gt 100 ] && { echo "strace did not attach" >&2; exit 1; }
      sleep 0.1
    done
    ;;
  stop)
    [ -f "$spid_file" ] && sudo -n kill -INT "$(cat "$spid_file")" 2>/dev/null
    i=0
    while [ -d "/proc/$mpid" ] && [ "$(tracer)" != "0" ]; do
      i=$((i+1)); [ $i -gt 100 ] && { echo "strace did not detach" >&2; exit 1; }
      sleep 0.1
    done
    ;;
  *) echo "usage: $0 start|stop <pid_file> <trace_file>" >&2; exit 2 ;;
esac
exit 0
