Esempio n. 1
0
def RunTest(random_filename):
    def _MakeTempFile(mode):
        return open(random_filename, mode)

    # Exercise metainformation and documentation strings
    assert distcc_pump_c_extensions.__file__
    assert distcc_pump_c_extensions.__doc__
    assert distcc_pump_c_extensions.__author__
    assert distcc_pump_c_extensions.RTokenString.__doc__
    assert distcc_pump_c_extensions.RArgv.__doc__
    assert distcc_pump_c_extensions.XArgv.__doc__
    assert distcc_pump_c_extensions.OsPathExists.__doc__
    assert distcc_pump_c_extensions.OsPathIsFile.__doc__
    assert distcc_pump_c_extensions.Realpath.__doc__

    # RTokenString and RArgv

    # Pack something and try sending it
    fd = _MakeTempFile('wb')
    fd.write('ARGC       2')
    fd.write('ARGV       6')
    fd.write('tomato')
    fd.write('ARGV       7')
    fd.write('potatos')
    fd.close()

    # Now try to read it back with wrong expectations.
    fd = _MakeTempFile('rb')
    try:
        two_string = distcc_pump_c_extensions.RTokenString(fd.fileno(), 'XXXX')
        sys.exit('internal error 1 - we should not get to here')
    except distcc_pump_c_extensions.Error:
        pass

    # Read it back with appropriate expectations.
    fd.seek(0)

    two_string = distcc_pump_c_extensions.RTokenString(fd.fileno(), 'ARGC')
    if two_string != 'AR':
        raise distcc_pump_c_extensions.error('internal error 2')

    fd.seek(0)
    args = distcc_pump_c_extensions.RArgv(fd.fileno())
    if args != ['tomato', 'potatos']:
        raise distcc_pump_c_extensions.error('internal error 3')
    fd.close()

    # XArgv and RArgv

    fd = _MakeTempFile('wb')
    darth_vader_barney = ['Darth Vader', 'Barney']
    args = distcc_pump_c_extensions.XArgv(fd.fileno(), darth_vader_barney)
    fd.close()

    fd = _MakeTempFile('r')
    args = distcc_pump_c_extensions.RArgv(fd.fileno())
    if args != darth_vader_barney:
        raise distcc_pump_c_extensions.error('internal error 4')
    fd.close()

    # Libc functions --- also print out how fast they are compared to
    # Python built-ins.
    t = time.time()
    f = '/'
    for unused_i in range(10000):
        distcc_pump_c_extensions.OsPathExists(f)
    print 'Stat', time.time() - t
    t = time.time()
    for unused_i in range(10000):
        os.path.exists(f)
    print 'os.path.exists', time.time() - t
    for unused_i in range(10000):
        distcc_pump_c_extensions.Realpath(f)
    print 'c_realpath', time.time() - t
    t = time.time()
    for unused_i in range(10000):
        os.path.realpath(f)
    print 'os.path.realpath', time.time() - t
    print 'c_extenstions_test passed'
Esempio n. 2
0
        def handle(self):
            """Using distcc protocol, read command and return include closure.

      Do the following:
       - Read from the socket, using the RPC protocol of distcc:
          - the current directory, and
          - the compilation command, already broken down into an argv vector.
       - Parse the command to find options like -I, -iquote,...
       - Invoke the include server's closure algorithm to yield a set of files
         and set of symbolic links --- both sets of files under client_root,
         which duplicates the part of the file system that CPP will need.
       - Transmit the file and link names on the socket using the RPC protocol.
      """
            statistics.StartTiming()
            currdir = distcc_pump_c_extensions.RCwd(self.rfile.fileno())
            cmd = distcc_pump_c_extensions.RArgv(self.rfile.fileno())

            try:
                try:
                    # We do timeout the include_analyzer using the crude mechanism of
                    # SIGALRM. This signal is problematic if raised while Python is doing
                    # I/O in the C extensions and during use of the subprocess
                    # module.
                    #
                    # TODO(klarlund) The Python library manual states: "When a signal
                    # arrives during an I/O operation, it is possible that the I/O
                    # operation raises an exception after the signal handler returns. This
                    # is dependent on the underlying Unix system's semantics regarding
                    # interrupted system calls."  We must clarify this. Currently, there
                    # is I/O during DoCompilationCommand:
                    #
                    #  - when a link is created in mirror_path.py
                    #  - module compress_files is used
                    #
                    # TODO(klarlund): Modify mirror_path so that is accumulates symbolic
                    # link operations instead of actually executing them on the spot. The
                    # accumulated operations can be executed after DoCompilationCommand
                    # when the timer has been cancelled.
                    include_analyzer.timer = basics.IncludeAnalyzerTimer()
                    files_and_links = (include_analyzer.DoCompilationCommand(
                        cmd, currdir, include_analyzer.client_root_keeper))
                finally:
                    # The timer should normally be cancelled during normal execution
                    # flow. Still, we want to make sure that this is indeed the case in
                    # all circumstances.
                    include_analyzer.timer.Cancel()

            except NotCoveredError, inst:
                # Warn user. The 'Preprocessing locally' message is meant to
                # assure the user that the build process is otherwise intact.
                fd = os.tmpfile()
                print >> fd, (
                    "Preprocessing locally. Include server not covering: %s for "
                    + "translation unit '%s'") % (
                        (inst.args and inst.args[0] or "unknown reason",
                         include_analyzer.translation_unit)),
                # We don't include a stack trace here.
                include_analyzer.email_sender.MaybeSendEmail(
                    fd, never=not inst.send_email)
                # The empty argv list denotes failure. Communicate this
                # information back to the distcc client, so that it can fall
                # back to preprocessing on the client.
                distcc_pump_c_extensions.XArgv(self.wfile.fileno(), [])
                if isinstance(inst, NotCoveredTimeOutError):
                    Debug(
                        DEBUG_TRACE,
                        "Clearing caches because of include server timeout.")
                    include_analyzer.ClearStatCaches()
Esempio n. 3
0
        def handle(self):
            """Using distcc protocol, read command and return include closure.

      Do the following:
       - Read from the socket, using the RPC protocol of distcc:
          - the current directory, and
          - the compilation command, already broken down into an argv vector.
       - Parse the command to find options like -I, -iquote,...
       - Invoke the include server's closure algorithm to yield a set of files
         and set of symbolic links --- both sets of files under client_root,
         which duplicates the part of the file system that CPP will need.
       - Transmit the file and link names on the socket using the RPC protocol.
      """
            statistics.StartTiming()
            currdir = distcc_pump_c_extensions.RCwd(self.rfile.fileno())
            cmd = distcc_pump_c_extensions.RArgv(self.rfile.fileno())

            try:
                try:
                    # We do timeout the include_analyzer using the crude mechanism of
                    # SIGALRM. This signal is problematic if raised while Python is doing
                    # I/O in the C extensions and during use of the subprocess
                    # module.
                    #
                    # TODO(klarlund) The Python library manual states: "When a signal
                    # arrives during an I/O operation, it is possible that the I/O
                    # operation raises an exception after the signal handler returns. This
                    # is dependent on the underlying Unix system's semantics regarding
                    # interrupted system calls."  We must clarify this. Currently, there
                    # is I/O during DoCompilationCommand:
                    #
                    #  - when a link is created in mirror_path.py
                    #  - module compress_files is used
                    #
                    # TODO(klarlund): Modify mirror_path so that is accumulates symbolic
                    # link operations instead of actually executing them on the spot. The
                    # accumulated operations can be executed after DoCompilationCommand
                    # when the timer has been cancelled.
                    include_analyzer.timer = basics.IncludeAnalyzerTimer()
                    files_and_links = (include_analyzer.DoCompilationCommand(
                        cmd, currdir, include_analyzer.client_root_keeper))
                finally:
                    # The timer should normally be cancelled during normal execution
                    # flow. Still, we want to make sure that this is indeed the case in
                    # all circumstances.
                    include_analyzer.timer.Cancel()

            except NotCoveredError as inst:
                # Warn user. The 'Preprocessing locally' message is meant to
                # assure the user that the build process is otherwise intact.
                fd = tempfile.TemporaryFile(mode='w+')
                print((
                    "Preprocessing locally. Include server not covering: %s for "
                    + "translation unit '%s'") %
                      ((inst.args and inst.args[0] or "unknown reason",
                        include_analyzer.translation_unit)),
                      file=fd,
                      end=' ')
                # We don't include a stack trace here.
                include_analyzer.email_sender.MaybeSendEmail(
                    fd, never=not inst.send_email)
                # The empty argv list denotes failure. Communicate this
                # information back to the distcc client, so that it can fall
                # back to preprocessing on the client.
                distcc_pump_c_extensions.XArgv(self.wfile.fileno(), [])
                if isinstance(inst, NotCoveredTimeOutError):
                    Debug(
                        DEBUG_TRACE,
                        "Clearing caches because of include server timeout.")
                    include_analyzer.ClearStatCaches()

            except SignalSIGTERM:
                # Normally, we will get this exception when the include server is no
                # longer needed. But we also handle it here, during the servicing of a
                # request. See basics.RaiseSignalSIGTERM.
                Debug(DEBUG_TRACE, "SIGTERM received while handling request.")
                raise
            except KeyboardInterrupt:
                # Propagate to the last-chance exception handler in Main.
                raise
            except SystemExit as inst:
                # When handler tries to exit (by invoking sys.exit, which in turn raises
                # SystemExit), something is really wrong. Terminate the include
                # server. But, print out an informative message first.
                fd = tempfile.TemporaryFile(mode='w+')
                print((
                    "Preprocessing locally. Include server fatal error: '%s' for "
                    + "translation unit '%s'") %
                      ((inst.args, include_analyzer.translation_unit)),
                      file=fd,
                      end=' ')
                _PrintStackTrace(fd)
                include_analyzer.email_sender.MaybeSendEmail(fd, force=True)
                distcc_pump_c_extensions.XArgv(self.wfile.fileno(), [])
                sys.exit("Now terminating include server.")
            # All other exceptions are trapped here.
            except Exception as inst:
                # Internal error. Better be safe than sorry: terminate include
                # server. But show error to user on stderr. We hope this message will be
                # reported.
                fd = tempfile.TemporaryFile(mode='w+')
                print((
                    "Preprocessing locally. Include server internal error: '%s: %s'"
                    + " for translation unit '%s'") %
                      ((inst.__class__, inst.args,
                        include_analyzer.translation_unit)),
                      file=fd)
                _PrintStackTrace(fd)
                # # Force this email through (if basics.opt_send_email is True), because
                # # this is the last one and this is an important case to report.
                include_analyzer.email_sender.MaybeSendEmail(fd, force=True)
                distcc_pump_c_extensions.XArgv(self.wfile.fileno(), [])
                raise SignalSIGTERM  # to be caught in Main with no further stack trace
            else:
                # No exception raised, include closure can be trusted.
                distcc_pump_c_extensions.XArgv(self.wfile.fileno(),
                                               files_and_links)
            # Print out observed paths.
            if basics.opt_path_observation_re:
                include_analyzer.build_stat_cache.WarnAboutPathObservations(
                    include_analyzer.translation_unit)
            # Finally, stop the clock and report statistics if needed.
            statistics.EndTiming()
            if basics.opt_statistics:
                statistics.PrintStatistics(include_analyzer)
Esempio n. 4
0
     raise
 except KeyboardInterrupt:
     # Propagate to the last-chance exception handler in Main.
     raise
 except SystemExit, inst:
     # When handler tries to exit (by invoking sys.exit, which in turn raises
     # SystemExit), something is really wrong. Terminate the include
     # server. But, print out an informative message first.
     fd = os.tmpfile()
     print >> fd, ((
         "Preprocessing locally. Include server fatal error: '%s' for "
         + "translation unit '%s'") % (
             (inst.args, include_analyzer.translation_unit))),
     _PrintStackTrace(fd)
     include_analyzer.email_sender.MaybeSendEmail(fd, force=True)
     distcc_pump_c_extensions.XArgv(self.wfile.fileno(), [])
     sys.exit("Now terminating include server.")
 # All other exceptions are trapped here.
 except Exception, inst:
     # Internal error. Better be safe than sorry: terminate include
     # server. But show error to user on stderr. We hope this message will be
     # reported.
     fd = os.tmpfile()
     print >> fd, ((
         "Preprocessing locally. Include server internal error: '%s: %s' "
         + "for translation unit '%s'") %
                   ((inst.__class__, inst.args,
                     include_analyzer.translation_unit))),
     _PrintStackTrace(fd)
     # Force this email through (if basics.opt_send_email is True), because
     # this is the last one and this is an important case to report.