Skip to content

Commit 9bb1a94

Browse files
committed
firewall: handle InterruptedError in get_connected_ips. Retry qdb.read to avoid startup crash. Added test.
1 parent 0a67a77 commit 9bb1a94

2 files changed

Lines changed: 30 additions & 1 deletion

File tree

qubesagent/firewall.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,13 @@ def update_connected_ips(self, family):
8282
raise NotImplementedError
8383

8484
def get_connected_ips(self, family):
85-
ips = self.qdb.read('/connected-ips6' if family == 6 else '/connected-ips')
85+
while True:
86+
try:
87+
ips = self.qdb.read(
88+
'/connected-ips6' if family == 6 else '/connected-ips')
89+
break
90+
except InterruptedError:
91+
continue
8692
if ips is None:
8793
return []
8894
return ips.decode().split()

qubesagent/test_firewall.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -572,3 +572,26 @@ def test_is_blocked(self):
572572

573573
for server in dns_servers_ipv6:
574574
self.assertTrue(self.obj.is_blocked(rules, ("udp", server, "53"), dns))
575+
576+
def test_get_connected_ips_retries_on_interrupted_error(self):
577+
#get_connected_ips() must retry qdb.read() on InterruptedError.
578+
#simulate SIGHUP interrupting qdb.read() on first call,
579+
#succeeding on second
580+
original_read = self.obj.qdb.read
581+
call_count = [0]
582+
583+
def read_with_interrupt(key):
584+
call_count[0] += 1
585+
if call_count[0] == 1:
586+
raise InterruptedError
587+
return original_read(key)
588+
589+
self.obj.qdb.entries['/connected-ips'] = b'10.137.0.1 10.137.0.2'
590+
self.obj.qdb.read = read_with_interrupt
591+
592+
#all the real get_connected_ips, not the overridden one
593+
result = qubesagent.firewall.FirewallWorker.get_connected_ips(
594+
self.obj, 4)
595+
596+
self.assertEqual(result, ['10.137.0.1', '10.137.0.2'])
597+
self.assertEqual(call_count[0], 2)

0 commit comments

Comments
 (0)