summaryrefslogtreecommitdiff
path: root/tests/test_mainloop.py
blob: 48399d15626836b7b0f08270aefe14476843f381 (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
# -*- Mode: Python -*-

import os
import select
import signal
import unittest

from gi.repository import GLib

from .helper import capture_exceptions


class TestMainLoop(unittest.TestCase):

    @unittest.skipUnless(hasattr(os, "fork"), "no os.fork available")
    def test_exception_handling(self):
        pipe_r, pipe_w = os.pipe()

        pid = os.fork()
        if pid == 0:
            os.close(pipe_w)
            select.select([pipe_r], [], [])
            os.close(pipe_r)
            os._exit(1)

        def child_died(pid, status, loop):
            loop.quit()
            raise Exception("deadbabe")

        loop = GLib.MainLoop()
        GLib.child_watch_add(GLib.PRIORITY_DEFAULT, pid, child_died, loop)

        os.close(pipe_r)
        os.write(pipe_w, b"Y")
        os.close(pipe_w)

        with capture_exceptions() as exc:
            loop.run()

        assert len(exc) == 1
        assert exc[0].type is Exception
        assert exc[0].value.args[0] == "deadbabe"

    @unittest.skipUnless(hasattr(os, "fork"), "no os.fork available")
    @unittest.skipIf(os.environ.get("PYGI_TEST_GDB"), "SIGINT stops gdb")
    def test_sigint(self):
        r, w = os.pipe()
        pid = os.fork()
        if pid == 0:
            # wait for the parent process loop to start
            os.read(r, 1)
            os.close(r)

            os.kill(os.getppid(), signal.SIGINT)
            os._exit(0)

        def notify_child():
            # tell the child that it can kill the parent
            os.write(w, b"X")
            os.close(w)

        GLib.idle_add(notify_child)
        loop = GLib.MainLoop()
        try:
            loop.run()
            self.fail('expected KeyboardInterrupt exception')
        except KeyboardInterrupt:
            pass
        self.assertFalse(loop.is_running())
        os.waitpid(pid, 0)