def execute_command(server_config, command, **kwargs):
    before_fds = _get_open_fds()  # see the comment in the finally clause below
    if isinstance(command, basestring):
        command = Command(command, **kwargs)
    timeout = 300 if command.name in ['stop', 'pull'] else 10
    factory = CommandExecutorFactory(server_config, command, timeout)

    # reactors aren't designed to be re-startable. In order to be
    # able to call execute_command multiple times, we need to froce
    # re-installation of the reactor; hence this hackery.
    # TODO: look into implementing restartable reactors. According to the
    #       Twisted FAQ, there is no good reason why there isn't one:
    #       http://twistedmatrix.com/trac/wiki/FrequentlyAskedQuestions#WhycanttheTwistedsreactorberestarted
    from twisted.internet import default
    del sys.modules['twisted.internet.reactor']
    default.install()
    global reactor  # pylint: disable=W0603
    reactor = sys.modules['twisted.internet.reactor']

    try:
        reactor.connectTCP(server_config.host, server_config.port, factory)
        reactor.run()
        return factory.result
    finally:
        # re-startable reactor hack part 2.
        # twisted hijacks SIGINT and doesn't bother to un-hijack it when the reactor
        # stops. So we have to do it for it *rolls eye*.
        import signal
        signal.signal(signal.SIGINT, signal.default_int_handler)
        # OK, the reactor is also leaking file descriptors. Tracking down all
        # of them is non trivial, so instead we're just comparing the before
        # and after lists of open FDs for the current process, and closing all
        # new ones, as execute_command should never leave anything open after
        # it exits (even when downloading data files from the server).
        # TODO: This is way too hacky even compared to the rest of this function.
        #       Additionally, the current implementation ties this to UNIX,
        #       so in the long run, we need to do this properly and get the FDs
        #       from the reactor.
        after_fds = _get_open_fds()
        for fd in after_fds - before_fds:
            try:
                os.close(int(fd[1:]))
            except __HOLE__:
                pass
        # Below is the alternative code that gets FDs from the reactor, however
        # at the moment it doesn't seem to get everything, which is why code
        # above is used instead.
        #for fd in readtor._selectables:
        #    os.close(fd)
        #reactor._poller.close()
dataset/ETHPy150Open ARM-software/workload-automation/wlauto/external/daq_server/src/daqpower/client.py/execute_command