Bug 1626590 Use os._exit not sys.exit in atexit in Python3 r=glandium,janerik
authorChris H-C <chutten@mozilla.com>
Tue, 14 Apr 2020 13:04:22 +0000
changeset 524404 a66e5e777cd16f0ee44e2c13eaab328854a9da5e
parent 524403 248ff2b5590595ba24a03690ec13b8a14753b3b3
child 524405 5dec62686a5f454d4abf0ed4dc9cf75821f6fd8b
push id113160
push userchutten@mozilla.com
push dateThu, 16 Apr 2020 13:30:09 +0000
treeherderautoland@a66e5e777cd1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglandium, janerik
bugs1626590
milestone77.0a1
first release with
nightly linux32
a66e5e777cd1 / 77.0a1 / 20200416214356 / files
nightly linux64
a66e5e777cd1 / 77.0a1 / 20200416214356 / files
nightly mac
a66e5e777cd1 / 77.0a1 / 20200416214356 / files
nightly win32
a66e5e777cd1 / 77.0a1 / 20200416214356 / files
nightly win64
a66e5e777cd1 / 77.0a1 / 20200416214356 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1626590 Use os._exit not sys.exit in atexit in Python3 r=glandium,janerik Also: os._exit is much faster than sys.exit, so remember to flush stderr or we won't see the errors we just printed. Also also: Mock os._exit to raise SystemExit in tests so that they can still run. (os._exit raises nothing and kills the test immediately) Differential Revision: https://phabricator.services.mozilla.com/D70047
toolkit/components/telemetry/build_scripts/mozparsers/shared_telemetry_utils.py
toolkit/components/telemetry/tests/python/test_histogramtools_strict.py
toolkit/components/telemetry/tests/python/test_parse_events.py
toolkit/components/telemetry/tests/python/test_parse_scalars.py
--- a/toolkit/components/telemetry/build_scripts/mozparsers/shared_telemetry_utils.py
+++ b/toolkit/components/telemetry/build_scripts/mozparsers/shared_telemetry_utils.py
@@ -2,19 +2,20 @@
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 # This file contains utility functions shared by the scalars and the histogram generation
 # scripts.
 
 from __future__ import print_function
 
+import os
 import re
+import sys
 import yaml
-import sys
 
 # This is a list of flags that determine which process a measurement is allowed
 # to record from.
 KNOWN_PROCESS_FLAGS = {
     'all': 'All',
     'all_children': 'AllChildren',
     'main': 'Main',
     'content': 'Content',
@@ -80,17 +81,18 @@ class ParserError(Exception):
         Exception.__init__(self, *args)
 
     def handle_later(self):
         ParserError.eventual_errors.append(self)
 
     def handle_now(self):
         ParserError.print_eventuals()
         print(str(self), file=sys.stderr)
-        sys.exit(1)
+        sys.stderr.flush()
+        os._exit(1)
 
     @classmethod
     def print_eventuals(cls):
         while cls.eventual_errors:
             print(str(cls.eventual_errors.pop(0)), file=sys.stderr)
 
     @classmethod
     def exit_func(cls):
--- a/toolkit/components/telemetry/tests/python/test_histogramtools_strict.py
+++ b/toolkit/components/telemetry/tests/python/test_histogramtools_strict.py
@@ -1,28 +1,38 @@
 # This Source Code Form is subject to the terms of the Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import mozunit
 import sys
 import unittest
+import os
 from os import path
 from test_histogramtools_non_strict import load_histogram
 
 TELEMETRY_ROOT_PATH = path.abspath(path.join(path.dirname(__file__), path.pardir, path.pardir))
 sys.path.append(TELEMETRY_ROOT_PATH)
 # The parsers live in a subdirectory of "build_scripts", account for that.
 # NOTE: if the parsers are moved, this logic will need to be updated.
 sys.path.append(path.join(TELEMETRY_ROOT_PATH, "build_scripts"))
 from mozparsers.shared_telemetry_utils import ParserError
 from mozparsers import parse_histograms
 
 
 class TestParser(unittest.TestCase):
+    def setUp(self):
+        def mockexit(x):
+            raise SystemExit(x)
+        self.oldexit = os._exit
+        os._exit = mockexit
+
+    def tearDown(self):
+        os._exit = self.oldexit
+
     def test_valid_histogram(self):
         SAMPLE_HISTOGRAM = {
             "TEST_VALID_HISTOGRAM": {
                 "record_in_processes": ["main", "content", "socket"],
                 "alert_emails": ["team@mozilla.xyz"],
                 "bug_numbers": [1383793],
                 "expires_in_version": "never",
                 "kind": "boolean",
--- a/toolkit/components/telemetry/tests/python/test_parse_events.py
+++ b/toolkit/components/telemetry/tests/python/test_parse_events.py
@@ -1,16 +1,17 @@
 # This Source Code Form is subject to the terms of Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import yaml
 import mozunit
 import sys
 import unittest
+import os
 from os import path
 
 TELEMETRY_ROOT_PATH = path.abspath(path.join(path.dirname(__file__), path.pardir, path.pardir))
 sys.path.append(TELEMETRY_ROOT_PATH)
 # The parsers live in a subdirectory of "build_scripts", account for that.
 # NOTE: if the parsers are moved, this logic will need to be updated.
 sys.path.append(path.join(TELEMETRY_ROOT_PATH, "build_scripts"))
 from mozparsers.shared_telemetry_utils import ParserError
@@ -22,16 +23,25 @@ def load_event(event):
 
     :param event: Event as YAML string
     :returns: Parsed Event dictionary
     """
     return yaml.safe_load(event)
 
 
 class TestParser(unittest.TestCase):
+    def setUp(self):
+        def mockexit(x):
+            raise SystemExit(x)
+        self.oldexit = os._exit
+        os._exit = mockexit
+
+    def tearDown(self):
+        os._exit = self.oldexit
+
     def test_valid_event_defaults(self):
         SAMPLE_EVENT = """
 objects: ["object1", "object2"]
 bug_numbers: [12345]
 notification_emails: ["test01@mozilla.com", "test02@mozilla.com"]
 record_in_processes: ["main"]
 description: This is a test entry for Telemetry.
 products: ["firefox"]
--- a/toolkit/components/telemetry/tests/python/test_parse_scalars.py
+++ b/toolkit/components/telemetry/tests/python/test_parse_scalars.py
@@ -1,16 +1,17 @@
 # This Source Code Form is subject to the terms of Mozilla Public
 # License, v. 2.0. If a copy of the MPL was not distributed with this
 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
 
 import yaml
 import mozunit
 import sys
 import unittest
+import os
 from os import path
 
 TELEMETRY_ROOT_PATH = path.abspath(path.join(path.dirname(__file__), path.pardir, path.pardir))
 sys.path.append(TELEMETRY_ROOT_PATH)
 # The parsers live in a subdirectory of "build_scripts", account for that.
 # NOTE: if the parsers are moved, this logic will need to be updated.
 sys.path.append(path.join(TELEMETRY_ROOT_PATH, "build_scripts"))
 from mozparsers.shared_telemetry_utils import ParserError
@@ -22,16 +23,25 @@ def load_scalar(scalar):
 
     :param scalar: Scalar as YAML string
     :returns: Parsed Scalar dictionary
     """
     return yaml.safe_load(scalar)
 
 
 class TestParser(unittest.TestCase):
+    def setUp(self):
+        def mockexit(x):
+            raise SystemExit(x)
+        self.oldexit = os._exit
+        os._exit = mockexit
+
+    def tearDown(self):
+        os._exit = self.oldexit
+
     def test_valid_email_address(self):
         SAMPLE_SCALAR_VALID_ADDRESSES = """
 description: A nice one-line description.
 expires: never
 record_in_processes:
   - 'main'
 kind: uint
 notification_emails: