Skip to content

Commit 68847ac

Browse files
committed
cleanup local variables in signal handler
1 parent 31341d3 commit 68847ac

File tree

5 files changed

+94
-29
lines changed

5 files changed

+94
-29
lines changed

setup.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
setup(
44
name = 'stackimpact',
5-
version = '1.0.2',
5+
version = '1.0.3',
66
description = 'StackImpact Python Agent',
77
author = 'StackImpact',
88
author_email = 'devops@stackimpact.com',
@@ -29,6 +29,7 @@
2929
'Programming Language :: Python :: 3.4',
3030
'Programming Language :: Python :: 3.5',
3131
'Programming Language :: Python :: 3.6',
32+
'Programming Language :: Python :: Implementation :: CPython',
3233
'Topic :: Software Development',
3334
'Topic :: System :: Monitoring',
3435
],

stackimpact/agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626

2727
class Agent:
2828

29-
AGENT_VERSION = "1.0.2"
29+
AGENT_VERSION = "1.0.3"
3030
SAAS_DASHBOARD_ADDRESS = "https://agent-api.stackimpact.com"
3131

3232
def __init__(self, **kwargs):

stackimpact/reporters/block_reporter.py

Lines changed: 30 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ def start(self):
3838
return
3939

4040
if not runtime_info.OS_LINUX and not runtime_info.OS_DARWIN:
41-
self.agent.log('Time profiler is only supported on Linux and OS X.')
41+
self.agent.log('Block profiler is only supported on Linux and OS X.')
4242
return
4343

4444
sample_time = self.SAMPLING_RATE * 1000
@@ -56,20 +56,8 @@ def _sample(signum, signal_frame):
5656

5757
with self.profile_lock:
5858
try:
59-
if self.block_profile:
60-
start = time.clock()
61-
62-
current_frames = sys._current_frames()
63-
for thread_id, thread_frame in current_frames.items():
64-
if thread_id == main_thread_id:
65-
thread_frame = signal_frame
66-
67-
stack = self.recover_stack(thread_frame)
68-
if stack:
69-
self.update_block_profile(stack, sample_time)
70-
self.update_http_profile(stack, sample_time)
71-
72-
self.block_profile._overhead += (time.clock() - start)
59+
self.process_sample(signal_frame, sample_time, main_thread_id)
60+
signal_frame = None
7361
except Exception:
7462
self.agent.exception()
7563

@@ -86,7 +74,8 @@ def destroy(self):
8674
if self.agent.get_option('block_profiler_disabled'):
8775
return
8876

89-
if self.prev_signal_handler:
77+
if self.prev_signal_handler != None:
78+
signal.setitimer(signal.ITIMER_REAL, 0)
9079
signal.signal(signal.SIGALRM, self.prev_signal_handler)
9180

9281
if self.profiler_scheduler:
@@ -103,17 +92,39 @@ def record(self, duration):
10392
if self.agent.config.is_profiling_disabled():
10493
return
10594

106-
self.agent.log('Activating blocking call profiler.')
95+
self.agent.log('Activating block profiler.')
10796

10897
signal.setitimer(signal.ITIMER_REAL, self.SAMPLING_RATE, self.SAMPLING_RATE)
10998
time.sleep(duration)
11099
signal.setitimer(signal.ITIMER_REAL, 0)
111100

112-
self.agent.log('Deactivating blocking call profiler.')
101+
self.agent.log('Deactivating block profiler.')
113102

114103
self.profile_duration += duration
115104

116-
self.agent.log('Time profiler CPU overhead per activity second: {0} seconds'.format(self.block_profile._overhead / self.profile_duration))
105+
self.agent.log('Block profiler CPU overhead per activity second: {0} seconds'.format(self.block_profile._overhead / self.profile_duration))
106+
107+
108+
def process_sample(self, signal_frame, sample_time, main_thread_id):
109+
if self.block_profile:
110+
start = time.clock()
111+
112+
current_frames = sys._current_frames()
113+
for thread_id, thread_frame in current_frames.items():
114+
if thread_id == main_thread_id:
115+
thread_frame = signal_frame
116+
117+
stack = self.recover_stack(thread_frame)
118+
if stack:
119+
self.update_block_profile(stack, sample_time)
120+
self.update_http_profile(stack, sample_time)
121+
122+
thread_id, thread_frame, stack = None, None, None
123+
124+
current_frames = None
125+
126+
self.block_profile._overhead += (time.clock() - start)
127+
117128

118129

119130
def recover_stack(self, thread_frame):

stackimpact/reporters/cpu_reporter.py

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -45,13 +45,8 @@ def _sample(signum, signal_frame):
4545

4646
with self.profile_lock:
4747
try:
48-
if self.profile:
49-
start = time.clock()
50-
if signal_frame:
51-
stack = self.recover_stack(signal_frame)
52-
if stack:
53-
self.update_profile(self.profile, stack)
54-
self.profile._overhead += (time.clock() - start)
48+
self.process_sample(signal_frame)
49+
signal_frame = None
5550
except Exception:
5651
self.agent.exception()
5752

@@ -69,7 +64,8 @@ def destroy(self):
6964
if self.agent.get_option('cpu_profiler_disabled'):
7065
return
7166

72-
if self.prev_signal_handler:
67+
if self.prev_signal_handler != None:
68+
signal.setitimer(signal.ITIMER_PROF, 0)
7369
signal.signal(signal.SIGPROF, self.prev_signal_handler)
7470

7571
if self.profiler_scheduler:
@@ -99,6 +95,19 @@ def record(self, duration):
9995
self.agent.log('CPU profiler CPU overhead per activity second: {0} seconds'.format(self.profile._overhead / self.profile_duration))
10096

10197

98+
def process_sample(self, signal_frame):
99+
if self.profile:
100+
start = time.clock()
101+
if signal_frame:
102+
stack = self.recover_stack(signal_frame)
103+
if stack:
104+
self.update_profile(self.profile, stack)
105+
106+
stack = None
107+
108+
self.profile._overhead += (time.clock() - start)
109+
110+
102111
def recover_stack(self, signal_frame):
103112
stack = []
104113

tests/runtime_test.py

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
import unittest
2+
import signal
3+
import os
4+
5+
import stackimpact
6+
from stackimpact.runtime import register_signal
7+
8+
9+
class RuntimeTestCase(unittest.TestCase):
10+
11+
def test_register_signal(self):
12+
result = {'handler': 0}
13+
14+
def _handler(signum, frame):
15+
result['handler'] += 1
16+
17+
register_signal(signal.SIGUSR1, _handler)
18+
19+
os.kill(os.getpid(), signal.SIGUSR1)
20+
os.kill(os.getpid(), signal.SIGUSR1)
21+
22+
signal.signal(signal.SIGUSR1, signal.SIG_DFL)
23+
24+
self.assertEqual(result['handler'], 2)
25+
26+
27+
'''def test_register_signal_default(self):
28+
result = {'handler': 0}
29+
30+
def _handler(signum, frame):
31+
result['handler'] += 1
32+
33+
register_signal(signal.SIGUSR1, _handler, ignore_default = False)
34+
35+
os.kill(os.getpid(), signal.SIGUSR1)
36+
os.kill(os.getpid(), signal.SIGUSR1)
37+
38+
self.assertEqual(result['handler'], 1)'''
39+
40+
41+
if __name__ == '__main__':
42+
unittest.main()
43+
44+

0 commit comments

Comments
 (0)