def reopen_log_files(handlers):
    """
    This method iterates through all of the providers handlers looking for the FileHandler types.

    A lock is acquired, the underlying stream closed, reopened, then the lock is released.


    This method should be called when logs are to be rotated by an external process. The simplest
    way to do this is via a signal handler.
    """
    for handler in handlers:
        if not isinstance(handler, logging.FileHandler):
            continue

        LOG.info(
            'Re-opening log file "%s" with mode "%s"\n'
            % (handler.baseFilename, handler.mode)
        )

        try:
            handler.acquire()
            handler.stream.close()
            handler.stream = open(handler.baseFilename, handler.mode)
        finally:
            try:
                handler.release()
            except RuntimeError as e:
                if "cannot release" in six.text_type(e):
                    # Release failed which most likely indicates that acquire failed
                    # and lock was never acquired
                    LOG.warning("Failed to release lock", exc_info=True)
                else:
                    raise e

    This method iterates through all of the providers handlers looking for the FileHandler types.

    A lock is acquired, the underlying stream closed, reopened, then the lock is released.


    This method should be called when logs are to be rotated by an external process. The simplest
    way to do this is via a signal handler.
    
st2common/st2common/logging/misc.py