blob: 32888ecc0559a9a4126f3cd8ad6ac1f5523c0d63 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
|
#!/bin/bash
# Compile server manager for systemtap
#
# Copyright (C) 2008 Red Hat Inc.
#
# This file is part of systemtap, and is free software. You can
# redistribute it and/or modify it under the terms of the GNU General
# Public License (GPL); either version 2, or (at your option) any
# later version.
# This script publishes its presence on the network and then listens for
# incoming connections. When a connection is detected, the stap-server script
# is run to handle the request.
# Catch ctrl-c and other termination signals
trap 'terminate' SIGTERM SIGINT
#-----------------------------------------------------------------------------
# Helper functions.
#-----------------------------------------------------------------------------
# function: initialization PORT
function initialization {
# Default settings.
tmpdir_prefix_serverd=stap.serverd
avahi_type=_stap._tcp
port=$1
test "X$port" = "X" && port=65000
port2=$(($port + 1))
if netstat -atn | awk '{print $4}' | cut -f2 -d: | egrep -q "^($port|$port2)\$"; then
# Whoops, the port is busy; try another one.
initialization $((1024+($port + $RANDOM)%64000))
fi
}
# function: advertise_presence
#
# Advertise the availability of the server on the network.
function advertise_presence {
# Build up a string representing our server's properties.
# TODO: this needs fleshing out.
local sysinfo=`uname -rvm`
local txt="sysinfo=$sysinfo"
# Call avahi-publish-service to advertise our presence.
avahi-publish-service "Systemtap Compile Server on `uname -n`" \
$avahi_type $port "$txt" > /dev/null 2>&1 &
echo "Systemtap Compile Server on `uname -n` listening on port $port"
}
# function: listen
#
# Listen for and handle requests to the server.
function listen {
# Work in a temporary directory
tmpdir=`mktemp -dt $tmpdir_prefix_serverd.XXXXXX` || \
fatal "ERROR: cannot create temporary directory " $tmpdir
cd $tmpdir
# Create a fifo for communicating with the server
local fifo_name=$tmpdir_prefix_serverd.fifo
mknod $fifo_name p || \
fatal "ERROR: cannot create temporary fifo " $tmpdir/$fifo_name
# Loop forever accepting requests
first=1
set -o pipefail # We want the status of 'nc' not 'stap-server'.
while true
do
# Run this in the background and wait for it. This way any signals
# received (i.e. SIGTERM) will be processed. Make sure we don't
# advertise our presence until we're actually listening.
for ((attempt=0; $attempt < 5; ++attempt))
do
nc -l $port < $fifo_name | stap-server $((port + 1)) > $fifo_name 2>&1 &
if test $first = 1; then
advertise_presence
first=0
fi
wait %nc
rc=$?
if test $rc = 127 -o $rc = 0; then
break; # success
fi
sleep 1
done
if test $attempt = 10; then
fatal "ERROR: cannot listen on port $port. rc==$rc"
fi
done
set +o pipefail # restore
}
# function: fatal [ MESSAGE ]
#
# Fatal error
# Prints its arguments to stderr and exits
function fatal {
echo "$@" >&2
terminate
exit 1
}
# function: terminate
#
# Terminate gracefully.
function terminate {
echo "$0: Exiting"
# Kill the running 'avahi-publish-service' job
kill -s SIGTERM %avahi-publish-service 2> /dev/null
wait %avahi-publish-service 2> /dev/null
# Kill any running 'nc -l' job.
kill -s SIGTERM "%nc -l" 2> /dev/null
wait "%nc - l" 2> /dev/null
# Clean up
cd `dirname $tmpdir`
rm -fr $tmpdir
exit
}
#-----------------------------------------------------------------------------
# Beginning of main line execution.
#-----------------------------------------------------------------------------
initialization "$@"
listen
|