Skip to content

bpo-31479: Always reset the signal alarm in tests#3588

Merged
vstinner merged 4 commits into
python:masterfrom
vstinner:reset_alarm
Sep 19, 2017
Merged

bpo-31479: Always reset the signal alarm in tests#3588
vstinner merged 4 commits into
python:masterfrom
vstinner:reset_alarm

Conversation

@vstinner

@vstinner vstinner commented Sep 14, 2017

Copy link
Copy Markdown
Member

Use "try: ... finally: signal.signal(0)" pattern to make sure that
tests don't "leak" a pending fatal signal alarm.

https://bugs.python.org/issue31479

Use "try: ... finally: signal.signal(0)" pattern to make sure that
tests don't "leak" a pending fatal signal alarm.
# select() was interrupted before the timeout of 30 seconds
self.assertLess(time() - t, 5.0)
try:
s.register(rd, selectors.EVENT_READ)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if the process is switched before this line, paused on more than 1 sec, and a SIGALRM signal is raised before registering a selector?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I moved the signal.alarm(1) into the try/except.

"

"What if (...) a SIGALRM signal is raised before registering a selector?" : the test would fail, no? In my PR, I only care of making sure that a scheduled alarm is always cancelled if something goes wrong.

# raise an exception, so select() should by retries with a recomputed
# timeout
self.assertFalse(s.select(1.5))
self.assertGreaterEqual(time() - t, 1.0)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't t be calculated before signal.alarm(1)?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think that this question is related to my change. If you would like to enhance test_selectors.py, please propose a different PR. I'm not aware of any issue with the existing code.

(I don't know if the line should be moved or not.)

But I also moved signal.alarm(1) into the try block.

Comment thread Lib/test/test_socket.py
with self.assertRaises(ZeroDivisionError) as cm:
func(*args, **kwargs)
try:
self.setAlarm(self.alarm_time)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be outside of the try block?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you press CTRL+c to interrupt the test just after setAlarm() but before entering the try block, the scheduled alarm is not cancelled. The purpose of my change is to make sure that it's always cancelled.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification.

Comment thread Lib/test/test_socket.py
try:
signal.alarm(2) # POSIX allows alarm to be up to 1 second early
try:
signal.alarm(2) # POSIX allows alarm to be up to 1 second early

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is moved?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same reason than my previous comment.

Comment thread Lib/test/test_pty.py
# before running the test to make sure we don't hang forever.
self.old_alarm = signal.signal(signal.SIGALRM, self.handle_sig)
old_alarm = signal.signal(signal.SIGALRM, self.handle_sig)
self.addCleanup(signal.signal, signal.SIGALRM, old_alarm)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why this is changed?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In my experience, tearDown() is an called if a test raises an exception. But I'm not sure about that.

Well, I also like the addCleanup() API to move the cleanup code closer to the setup code.

self.wait_signal(None, 'SIGALRM', KeyboardInterrupt)
self.assertEqual(self.got_signals, {'SIGHUP': 1, 'SIGUSR1': 1,
'SIGALRM': 0})
try:

@serhiy-storchaka serhiy-storchaka Sep 16, 2017

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move signal.alarm(1) into a 'try' block?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment thread Lib/test/test_socket.py
with self.assertRaises(ZeroDivisionError) as cm:
func(*args, **kwargs)
try:
self.setAlarm(self.alarm_time)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the clarification.

@serhiy-storchaka

Copy link
Copy Markdown
Member

Would a special context manager make the code clearer?

@vstinner

Copy link
Copy Markdown
Member Author

Would a special context manager make the code clearer?

I'm not sure that it's easy to factorize the code since many tests are different. I let you try the exercice if you want :-)

@vstinner vstinner merged commit 9abee72 into python:master Sep 19, 2017
@vstinner vstinner deleted the reset_alarm branch September 19, 2017 16:36
@vstinner

Copy link
Copy Markdown
Member Author

Crap, as usual I forgot to modify the commit message :-(

vstinner added a commit that referenced this pull request Jun 1, 2018
* bpo-31479: Always reset the signal alarm in tests

Use "try: ... finally: signal.signal(0)" pattern to make sure that
tests don't "leak" a pending fatal signal alarm.

* Move two more alarm() calls into the try block

Fix also typo: replace signal.signal(0) with signal.alarm(0)

* Move another signal.alarm() into the try block

(cherry picked from commit 9abee72)
vstinner added a commit that referenced this pull request Jun 1, 2018
* bpo-31479: Always reset the signal alarm in tests

Use "try: ... finally: signal.signal(0)" pattern to make sure that
tests don't "leak" a pending fatal signal alarm.

* Move two more alarm() calls into the try block

Fix also typo: replace signal.signal(0) with signal.alarm(0)

* Move another signal.alarm() into the try block

(cherry picked from commit 9abee72)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants