# Buggy code
def salt_minion():
    """
    Start the salt minion.
    """
    import salt.cli.daemons
    import multiprocessing

    if "" in sys.path:
        sys.path.remove("")

    if salt.utils.is_windows():
        minion = salt.cli.daemons.Minion()
        minion.start()
        return

    if "--disable-keepalive" in sys.argv:
        sys.argv.remove("--disable-keepalive")
        minion = salt.cli.daemons.Minion()
        minion.start()
        return

    # keep one minion subprocess running
    while True:
        try:
            queue = multiprocessing.Queue()
        except Exception:
            # This breaks in containers
            minion = salt.cli.daemons.Minion()
            minion.start()
            return
        process = multiprocessing.Process(target=minion_process, args=(queue,))
        process.start()
        try:
            process.join()
            try:
                restart_delay = queue.get(block=False)
            except Exception:
                if process.exitcode == 0:
                    # Minion process ended naturally, Ctrl+C or --version
                    break
                restart_delay = 60
            if restart_delay == 0:
                # Minion process ended naturally, Ctrl+C, --version, etc.
                break
            # delay restart to reduce flooding and allow network resources to close
            time.sleep(restart_delay)
        except KeyboardInterrupt:
            break
        # need to reset logging because new minion objects
        # cause extra log handlers to accumulate
        rlogger = logging.getLogger()
        for handler in rlogger.handlers:
            rlogger.removeHandler(handler)
        logging.basicConfig()


# Traceback (SaltClientError)
PS C:\salt> .\salt-minion.bat -ldebug
[DEBUG   ] Reading configuration from c:\salt\conf\minion
[DEBUG   ] Including configuration from 'c:\salt\conf\minion.d\_schedule.conf'
[DEBUG   ] Reading configuration from c:\salt\conf\minion.d\_schedule.conf
[DEBUG   ] Configuration file path: c:\salt\conf\minion
[WARNING ] Insecure logging configuration detected! Sensitive data may be logged.
[INFO    ] Setting up the Salt Minion "win2012"
[DEBUG   ] Created pidfile: c:\salt\var\run\salt-minion.pid
[DEBUG   ] Reading configuration from c:\salt\conf\minion
[DEBUG   ] Including configuration from 'c:\salt\conf\minion.d\_schedule.conf'
[DEBUG   ] Reading configuration from c:\salt\conf\minion.d\_schedule.conf
[INFO    ] Creating minion process manager
[WARNING ] IMPORTANT: Do not use md5 hashing algorithm! Please set "hash_type" to sha256 in Salt Minion config!
[INFO    ] The Salt Minion is starting up
[INFO    ] Minion is starting as user 'ch3ll'
[DEBUG   ] AsyncEventPublisher PUB socket URI: 4510
[DEBUG   ] AsyncEventPublisher PULL socket URI: 4511
[INFO    ] Starting pull socket on 4511
[DEBUG   ] Minion 'win2012' trying to tune in
[DEBUG   ] sync_connect_master
[CRITICAL] 'master_type' set to 'failover' but 'retry_dns' is not 0. Setting 'retry_dns' to 0 to failover to the next m
ster on DNS errors.
[DEBUG   ] Connecting to master. Attempt 1 of 1
[DEBUG   ] Initializing new AsyncAuth for ('c:\\salt\\conf\\pki\\minion', 'win2012', 'tcp://192.168.50.10:4506')
[DEBUG   ] Generated random reconnect delay between '1000ms' and '11000ms' (2296)
[DEBUG   ] Setting zmq_reconnect_ivl to '2296ms'
[DEBUG   ] Setting zmq_reconnect_ivl_max to '11000ms'
[DEBUG   ] Process Manager starting!
[DEBUG   ] Initializing new AsyncZeroMQReqChannel for ('c:\\salt\\conf\\pki\\minion', 'win2012', 'tcp://192.168.50.10:4
06', 'clear')
[DEBUG   ] SaltReqTimeoutError, retrying. (1/7)
[DEBUG   ] SaltReqTimeoutError, retrying. (2/7)
[DEBUG   ] SaltReqTimeoutError, retrying. (3/7)
[DEBUG   ] SaltReqTimeoutError, retrying. (4/7)
[DEBUG   ] SaltReqTimeoutError, retrying. (5/7)
[DEBUG   ] SaltReqTimeoutError, retrying. (6/7)
[DEBUG   ] SaltReqTimeoutError, retrying. (7/7)
[INFO    ] Master 192.168.50.10 could not be reached, trying next master (if any)
[ERROR   ] No master could be reached or all masters denied the minions connection attempt.
[ERROR   ] An un-handled exception was caught by salt's global exception handler:
SaltClientError: Attempt to authenticate with the salt master failed with timeout error
Traceback (most recent call last):
File "C:\salt\bin\Scripts\salt-minion", line 26, in <module>
salt_minion()
File "C:\salt\bin\lib\site-packages\salt\scripts.py", line 112, in salt_minion
minion.start()
File "C:\salt\bin\lib\site-packages\salt\cli\daemons.py", line 349, in start
self.minion.tune_in()
File "C:\salt\bin\lib\site-packages\salt\minion.py", line 1961, in tune_in
self.sync_connect_master()
File "C:\salt\bin\lib\site-packages\salt\minion.py", line 896, in sync_connect_master
raise six.reraise(*future_exception)
File "C:\salt\bin\lib\site-packages\tornado\gen.py", line 1014, in run
yielded = self.gen.throw(*exc_info)
File "C:\salt\bin\lib\site-packages\salt\minion.py", line 905, in connect_master
master, self.pub_channel = yield self.eval_master(self.opts, self.timeout, self.safe)
File "C:\salt\bin\lib\site-packages\tornado\gen.py", line 1008, in run
value = future.result()
File "C:\salt\bin\lib\site-packages\tornado\concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "C:\salt\bin\lib\site-packages\tornado\gen.py", line 1014, in run
yielded = self.gen.throw(*exc_info)
File "C:\salt\bin\lib\site-packages\salt\minion.py", line 540, in eval_master
raise last_exc  # pylint: disable=E0702
SaltClientError: Attempt to authenticate with the salt master failed with timeout error
Traceback (most recent call last):
File "C:\salt\bin\Scripts\salt-minion", line 26, in <module>
salt_minion()
File "C:\salt\bin\lib\site-packages\salt\scripts.py", line 112, in salt_minion
minion.start()
File "C:\salt\bin\lib\site-packages\salt\cli\daemons.py", line 349, in start
self.minion.tune_in()
File "C:\salt\bin\lib\site-packages\salt\minion.py", line 1961, in tune_in
self.sync_connect_master()
File "C:\salt\bin\lib\site-packages\salt\minion.py", line 896, in sync_connect_master
raise six.reraise(*future_exception)
File "C:\salt\bin\lib\site-packages\tornado\gen.py", line 1014, in run
yielded = self.gen.throw(*exc_info)
File "C:\salt\bin\lib\site-packages\salt\minion.py", line 905, in connect_master
master, self.pub_channel = yield self.eval_master(self.opts, self.timeout, self.safe)
File "C:\salt\bin\lib\site-packages\tornado\gen.py", line 1008, in run
value = future.result()
File "C:\salt\bin\lib\site-packages\tornado\concurrent.py", line 232, in result
raise_exc_info(self._exc_info)
File "C:\salt\bin\lib\site-packages\tornado\gen.py", line 1014, in run
yielded = self.gen.throw(*exc_info)
File "C:\salt\bin\lib\site-packages\salt\minion.py", line 540, in eval_master
raise last_exc  # pylint: disable=E0702
salt.exceptions.SaltClientError: Attempt to authenticate with the salt master failed with timeout error

# Fixed code
def salt_minion():
    """
    Start the salt minion.
    """
    import salt.cli.daemons
    import multiprocessing

    if "" in sys.path:
        sys.path.remove("")

    if "--disable-keepalive" in sys.argv:
        sys.argv.remove("--disable-keepalive")
        minion = salt.cli.daemons.Minion()
        minion.start()
        return

    # keep one minion subprocess running
    while True:
        try:
            queue = multiprocessing.Queue()
        except Exception:
            # This breaks in containers
            minion = salt.cli.daemons.Minion()
            minion.start()
            return
        process = multiprocessing.Process(target=minion_process, args=(queue,))
        process.start()
        try:
            process.join()
            try:
                restart_delay = queue.get(block=False)
            except Exception:
                if process.exitcode == 0:
                    # Minion process ended naturally, Ctrl+C or --version
                    break
                restart_delay = 60
            if restart_delay == 0:
                # Minion process ended naturally, Ctrl+C, --version, etc.
                break
            # delay restart to reduce flooding and allow network resources to close
            time.sleep(restart_delay)
        except KeyboardInterrupt:
            break
        # need to reset logging because new minion objects
        # cause extra log handlers to accumulate
        rlogger = logging.getLogger()
        for handler in rlogger.handlers:
            rlogger.removeHandler(handler)
        logging.basicConfig()