10 from signal
import signal
, SIGTERM
, SIGINT
, SIGPIPE
, SIG_DFL
12 SESSIOND_BIN_NAME
= "lttng-sessiond"
13 SESSIOND_BIN_PATH
= "src/bin/lttng-sessiond/"
14 CONSUMERD_BIN_NAME
= "lttng-consumerd"
15 CONSUMERD_BIN_PATH
= "src/bin/lttng-consumerd/"
18 PRINT_BRACKET
= "\033[1;34m[\033[1;33m+\033[1;34m]\033[00m"
19 PRINT_RED_BRACKET
= "\033[1;31m[+]\033[00m"
20 PRINT_GREEN_BRACKET
= "\033[1;32m[+]\033[00m"
21 PRINT_ARROW
= "\033[1;32m-->\033[00m"
27 top_cpu_legend
= { 'us': "User CPU time", 'sy': "System CPU time",
28 'id': "Idle CPU time", 'ni': "Nice CPU time", 'wa': "iowait",
29 'hi': "Hardware IRQ", 'si': "Software Interrupts", 'st': "Steal Time", }
31 cpu_ret_q
= Queue
.Queue()
32 mem_ret_q
= Queue
.Queue()
33 test_ret_q
= Queue
.Queue()
38 def cpu_create_usage_dict(top_line
):
40 Return a dictionnary from a 'top' cpu line.
41 Ex: Cpu(s): 2.1%us, 1.2%sy, 0.0%ni, 96.2%id, 0.4%wa, 0.0%hi, 0.0%si, 0.0%st
43 top_dict
= {'us': 0, 'sy': 0, 'ni': 0, 'id': 0, 'wa': 0, 'hi': 0, 'si': 0, 'st': 0}
45 # Split expression and remove first value which is "Cpu(s)"
46 top_line
= top_line
.replace(",","")
47 words
= top_line
.split()[1:]
51 index
= words
.index(key
)
52 # Add the value to the dictionnary
54 top_dict
[key
] = float(val
)
58 def cpu_average_usage(top_lines
):
60 Return a dictionnary of 'top' CPU stats but averaging all values.
62 avg_dict
= {'us': 0, 'sy': 0, 'ni': 0, 'id': 0, 'wa': 0, 'hi': 0, 'si': 0, 'st': 0}
66 for line
in top_lines
:
67 tmp_dict
= cpu_create_usage_dict(line
)
68 # Add value to avg dictionnary
70 avg_dict
[key
] += tmp_dict
[key
]
75 avg_dict
[key
] = avg_dict
[key
] / count
77 return (count
, avg_dict
)
79 def cpu_sample_usage(pid
=None):
81 Sample CPU usage for num iterations.
82 If num is greater than 1, the average will be computed.
84 args
= ["top", "-b", "-n", "1"]
90 top
= subprocess
.Popen(args
, stdout
= subprocess
.PIPE
)
92 grep
= subprocess
.Popen(["grep", "Cpu"], stdin
= top
.stdout
,
93 stdout
= subprocess
.PIPE
)
96 return grep
.communicate()[0].strip("\n")
98 def mem_sample_usage(pid
):
100 Sample memory usage using /proc and a pid
102 args
= ["cat", "/proc/" + str(pid
) + "/status"]
104 if not os
.path
.isfile(args
[1]):
107 mem_proc
= subprocess
.Popen(args
, stdout
= subprocess
.PIPE
)
109 grep
= subprocess
.Popen(["grep", "^VmRSS"], stdin
= mem_proc
.stdout
,
110 stdout
= subprocess
.PIPE
)
111 mem_proc
.stdout
.close()
113 # Return virtual memory size in kilobytes (kB)
114 #ret = grep.communicate()[0].split()
115 ret
= grep
.communicate()[0].split()
124 class SamplingWorker(threading
.Thread
):
125 def __init__(self
, s_type
, worker
= None, delay
= 0.2, pid
= 0):
126 threading
.Thread
.__init
__ (self
)
136 if self
.s_type
== "cpu":
138 if self
.worker
== None:
139 cpu_line
= cpu_sample_usage(self
.pid
)
140 lines
.append(cpu_line
)
142 elif self
.worker
.is_alive():
143 cpu_line
= cpu_sample_usage(self
.pid
)
144 lines
.append(cpu_line
)
148 # Delay sec per memory sampling
149 time
.sleep(self
.delay
)
151 count
, stats
= cpu_average_usage(lines
)
152 cpu_ret_q
.put((count
, stats
))
153 # grep process has ended here
155 elif self
.s_type
== "mem":
160 if self
.worker
== None:
161 cpu_line
= cpu_sample_usage(self
.pid
)
162 lines
.append(cpu_line
)
164 elif self
.worker
.is_alive():
165 mem_stat
+= get_mem_usage(self
.pid
)
170 # Delay sec per memory sampling
171 time
.sleep(self
.delay
)
173 mem_ret_q
.put((count
, mem_stat
))
175 class TestWorker(threading
.Thread
):
176 def __init__(self
, path
, name
, env
):
177 threading
.Thread
.__init
__(self
)
183 bin_path_name
= os
.path
.join(self
.path
, self
.name
)
185 test
= subprocess
.Popen([bin_path_name
], env
=self
.env
, preexec_fn
= lambda: signal(SIGPIPE
, SIG_DFL
))
188 # Send ret value to main thread
189 test_ret_q
.put(test
.returncode
)
191 def get_pid(procname
):
193 Return pid of process name using 'pidof' command
195 pidof
= subprocess
.Popen(["pidof", procname
], stdout
= subprocess
.PIPE
)
196 pid
= pidof
.communicate()[0].split()
203 def spawn_session_daemon():
205 Exec the session daemon and return PID
209 pid
= get_pid(SESSIOND_BIN_NAME
)
211 os
.kill(pid
, SIGTERM
)
213 bin_path
= os
.path
.join(TESTDIR_PATH
, "..", SESSIOND_BIN_PATH
, SESSIOND_BIN_NAME
)
214 consumer_path
= os
.path
.join(TESTDIR_PATH
, "..", CONSUMERD_BIN_PATH
, CONSUMERD_BIN_NAME
)
216 if not os
.path
.isfile(bin_path
):
217 print "Error: No session daemon binary found. Compiled?"
221 args
= shlex
.split("libtool execute " + bin_path
222 + " --consumerd32-path=" + consumer_path
223 + " --consumerd64-path=" + consumer_path
)
225 sdaemon_proc
= subprocess
.Popen(args
, shell
= False, stderr
= subprocess
.PIPE
)
233 return get_pid("lt-" + SESSIOND_BIN_NAME
)
235 def start_test(name
):
237 Spawn test and return exit code
239 tw
= TestWorker(".", name
)
242 return test_ret_q
.get(True)
244 def print_cpu_stats(stats
, count
):
246 Pretty print on one line the CPU stats
248 sys
.stdout
.write(PRINT_ARROW
+ " Cpu [sampled %d time(s)]:\n " % (count
))
250 sys
.stdout
.write(" %s: %.2f, " % (stat
, stats
[stat
]))
253 def get_cpu_usage(delay
=1, pid
=0):
255 Spawn a worker thread to sample cpu usage.
257 sw
= SamplingWorker("cpu", delay
= delay
, pid
= pid
)
260 return cpu_ret_q
.get(True)
262 def get_mem_usage(pid
):
264 Get memory usage for PID
266 return mem_sample_usage(pid
)
268 def print_test_success(ret
, expect
):
270 Print if test has failed or pass according to the expected value.
273 print "\n" + PRINT_RED_BRACKET
+ \
274 " Failed: ret = %d (expected %d)" % (ret
, expect
)
277 print "\n" + PRINT_BRACKET
+ \
278 " Passed: ret = %d (expected %d)" % (ret
, expect
)
283 Run test 'name' and output report of the test with stats.
287 dem_pid
= 0 # Session daemon pid
289 print PRINT_BRACKET
+ " %s" % (test
['name'])
290 print PRINT_ARROW
+ " %s" % (test
['desc'])
292 print PRINT_ARROW
+ " Statistics will NOT be collected"
294 print PRINT_ARROW
+ " Statistics of the session daemon will be collected"
296 if test
['kern'] and not is_root
:
297 print "Needs root for kernel tracing. Skipping"
300 if not os
.path
.isfile(test
['bin']):
301 print "Unable to find test file '%s'. Skipping" % (test
['bin'])
304 # Session daemon is controlled by the test
305 if test
['daemon'] == "test":
306 print PRINT_ARROW
+ " Session daemon is controlled by the test"
308 env
['TEST_NO_SESSIOND'] = '0'
309 tw
= TestWorker(".", test
['bin'], env
)
311 ret
= test_ret_q
.get(True)
312 print_test_success(ret
, test
['success'])
314 elif test
['daemon'] == False:
315 print PRINT_ARROW
+ " No session daemon needed"
317 env
['TEST_NO_SESSIOND'] = '1'
318 tw
= TestWorker(".", test
['bin'], env
)
320 ret
= test_ret_q
.get(True)
321 print_test_success(ret
, test
['success'])
324 print PRINT_ARROW
+ " Session daemon needed"
326 dem_pid
= spawn_session_daemon()
328 print "Unable to start %s. Stopping" % (SESSIOND_BIN_NAME
)
329 print sdaemon_proc
.communicate()[1]
332 print PRINT_BRACKET
+ " Session daemon spawned (pid: %d)\n" % (dem_pid
)
335 mem_before
= get_mem_usage(dem_pid
)
336 print PRINT_BRACKET
+ " Stats *before* test:"
337 print PRINT_ARROW
+ " Mem (kB): %d" % (mem_before
)
338 cpu_count
, cpu_stats
= get_cpu_usage(pid
= dem_pid
)
339 print_cpu_stats(cpu_stats
, cpu_count
)
341 # Sessiond was already spawned, do not let the test spawn
342 # an additional sessiond
344 env
['TEST_NO_SESSIOND'] = '1'
346 tw
= TestWorker(".", test
['bin'], env
)
350 # Start CPU sampling for test
351 sw_cpu
= SamplingWorker("cpu", worker
= tw
, pid
= dem_pid
)
353 sw_mem
= SamplingWorker("mem", worker
= tw
, pid
= dem_pid
)
356 ret
= test_ret_q
.get(True)
360 # Compute memory average
361 mem_count
, mem_during
= mem_ret_q
.get(True)
362 mem_during
= float(mem_during
) / float(mem_count
)
363 cpu_count
, cpu_stats
= cpu_ret_q
.get(True)
365 print "\n" + PRINT_BRACKET
+ " Stats *during* test:"
366 print PRINT_ARROW
+ " Mem (kB): %.0f [sampled %d time(s)]" % (mem_during
, mem_count
)
367 print_cpu_stats(cpu_stats
, cpu_count
)
369 mem_after
= get_mem_usage(dem_pid
)
370 print "\n" + PRINT_BRACKET
+ " Stats *after* test:"
371 print PRINT_ARROW
+ " Mem (kB): %d" % (mem_after
)
372 cpu_count
, cpu_stats
= get_cpu_usage(pid
= dem_pid
)
373 print_cpu_stats(cpu_stats
, cpu_count
)
375 print "\n" + PRINT_BRACKET
+ " Memory usage differences:"
376 print PRINT_ARROW
+ " Diff during and before (kB): %d" % (mem_during
- mem_before
)
377 print PRINT_ARROW
+ " Diff during and after (kB): %d" % (mem_during
- mem_after
)
378 print PRINT_ARROW
+ " Diff before and after (kB): %d" % (mem_after
- mem_before
)
380 # Return value of 0 means that is passed else it failed
381 ret
= print_test_success(ret
, test
['success'])
383 # Stop session daemon
385 print PRINT_BRACKET
+ " Stopping session daemon (pid: %d)..." % (dem_pid
)
387 os
.kill(dem_pid
, SIGTERM
)
388 # This call simply does not work... It seems python does not relay the signal
389 # to the child processes of sdaemon_proc.
390 # sdaemon_proc.terminate()
392 print sdaemon_proc
.communicate()[1]
393 elif sdaemon_proc
.returncode
== None:
394 sdaemon_proc
.communicate()
398 # Make sure all thread are released
408 if not test
['enabled']:
413 # Stop all tests, the last one failed
417 def cleanup(signo
, stack
):
418 """ Cleanup function """
421 if __name__
== "__main__":
422 if not os
.getuid() == 0:
424 print "NOTICE: Not root. No kernel tracing will be tested\n"
426 if os
.path
.isfile("test_list.py"):
427 from test_list
import Tests
429 print "No test_list.py found. Stopping"
432 TESTDIR_PATH
= os
.getcwd()
434 if len(sys
.argv
) > 1:
435 if sys
.argv
[1] == "--no-stats":
439 signal(SIGTERM
, cleanup
)
440 signal(SIGINT
, cleanup
)
443 except KeyboardInterrupt:
This page took 0.048459 seconds and 5 git commands to generate.