# Buggy code
def run_job_async(
    self,
    tgt,
    fun,
    arg=(),
    tgt_type="glob",
    ret="",
    timeout=None,
    jid="",
    kwarg=None,
    listen=True,
    io_loop=None,
    **kwargs,
):
    """
    Asynchronously send a command to connected minions

    Prep the job directory and publish a command to any targeted minions.

    :return: A dictionary of (validated) ``pub_data`` or an empty
        dictionary on failure. The ``pub_data`` contains the job ID and a
        list of all minions that are expected to return data.

    .. code-block:: python

        >>> local.run_job_async('*', 'test.sleep', [300])
        {'jid': '20131219215650131543', 'minions': ['jerry']}
    """
    if "expr_form" in kwargs:
        salt.utils.warn_until(
            "Fluorine",
            "The target type should be passed using the 'tgt_type' "
            "argument instead of 'expr_form'. Support for using "
            "'expr_form' will be removed in Salt Fluorine.",
        )
        tgt_type = kwargs.pop("expr_form")

    arg = salt.utils.args.condition_input(arg, kwarg)

    try:
        pub_data = yield self.pub_async(
            tgt,
            fun,
            arg,
            tgt_type,
            ret,
            jid=jid,
            timeout=self._get_timeout(timeout),
            io_loop=io_loop,
            listen=listen,
            **kwargs,
        )
    except SaltClientError:
        # Re-raise error with specific message
        raise SaltClientError(
            "The salt master could not be contacted. Is master running?"
        )
    except Exception as general_exception:
        # Convert to generic client error and pass along message
        raise SaltClientError(general_exception)

    raise tornado.gen.Return(self._check_pub_data(pub_data))


# Traceback (SaltClientError)
2017-03-20 15:58:15,317 [salt.utils.event                         ][DEBUG   ][28048] MasterEvent PUB socket URI: ipc:///var/run/salt/master/master_event_pub.ipc2017-03-20 15:58:15,318 [salt.utils.event                         ][DEBUG   ][28048] MasterEvent PULL socket URI: ipc:///var/run/salt/master/master_event_pull.ipc
Traceback (most recent call last):
File "/usr/lib/python2.6/site-packages/salt/netapi/rest_cherrypy/app.py", line 507, in hypermedia_handler
File "/usr/lib/python2.6/site-packages/cherrypy/_cpdispatch.py", line 34, in __call__
File "/usr/lib/python2.6/site-packages/salt/netapi/rest_cherrypy/app.py", line 933, in POST
File "/usr/lib/python2.6/site-packages/salt/netapi/rest_cherrypy/app.py", line 775, in exec_lowstate
File "/usr/lib/python2.6/site-packages/salt/netapi/__init__.py", line 70, in run
File "/usr/lib/python2.6/site-packages/salt/netapi/__init__.py", line 98, in local
File "/usr/lib/python2.6/site-packages/salt/client/__init__.py", line 535, in cmd
File "/usr/lib/python2.6/site-packages/salt/client/__init__.py", line 290, in run_job
SaltClientError: [Errno 24] Too many open files
2017-03-20 15:58:15,751 [salt.utils.process                       ][INFO    ][28040] Process <function start at 0x1ce6b18> (28048) died with exit status None, restarting...
2017-03-20 15:58:16,757 [salt.utils.process                       ][DEBUG   ][28040] Started 'salt.loaded.int.netapi.rest_cherrypy.start' with pid 20716

# Fixed code
def run_job_async(
    self,
    tgt,
    fun,
    arg=(),
    tgt_type="glob",
    ret="",
    timeout=None,
    jid="",
    kwarg=None,
    listen=True,
    io_loop=None,
    **kwargs,
):
    """
    Asynchronously send a command to connected minions

    Prep the job directory and publish a command to any targeted minions.

    :return: A dictionary of (validated) ``pub_data`` or an empty
        dictionary on failure. The ``pub_data`` contains the job ID and a
        list of all minions that are expected to return data.

    .. code-block:: python

        >>> local.run_job_async('*', 'test.sleep', [300])
        {'jid': '20131219215650131543', 'minions': ['jerry']}
    """
    if "expr_form" in kwargs:
        salt.utils.warn_until(
            "Fluorine",
            "The target type should be passed using the 'tgt_type' "
            "argument instead of 'expr_form'. Support for using "
            "'expr_form' will be removed in Salt Fluorine.",
        )
        tgt_type = kwargs.pop("expr_form")

    arg = salt.utils.args.condition_input(arg, kwarg)

    try:
        pub_data = yield self.pub_async(
            tgt,
            fun,
            arg,
            tgt_type,
            ret,
            jid=jid,
            timeout=self._get_timeout(timeout),
            io_loop=io_loop,
            listen=listen,
            **kwargs,
        )
    except SaltClientError:
        # Re-raise error with specific message
        raise SaltClientError(
            "The salt master could not be contacted. Is master running?"
        )
    except Exception as general_exception:
        # Convert to generic client error and pass along message
        raise SaltClientError(general_exception)

    raise tornado.gen.Return(self._check_pub_data(pub_data, listen=listen))