prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Log app args
  For easier debugging, we should log the arguments apps are called with.
  
  Requested by @mjwilde 
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `parsl/app/bash.py`
  Content:
  ```
  1 import logging
  2 from functools import update_wrapper
  3 from inspect import signature, Parameter
  4 
  5 from parsl.app.errors import wrap_error
  6 from parsl.app.futures import DataFuture
  7 from parsl.app.app import AppBase
  8 from parsl.dataflow.dflow import DataFlowKernelLoader
  9 
  10 logger = logging.getLogger(__name__)
  11 
  12 
  13 def remote_side_bash_executor(func, *args, **kwargs):
  14     """Execute the bash app type function and return the command line string.
  15 
  16     This string is reformatted with the *args, and **kwargs
  17     from call time.
  18     """
  19     import os
  20     import time
  21     import subprocess
  22     import logging
  23     import parsl.app.errors as pe
  24 
  25     logging.basicConfig(filename='/tmp/bashexec.{0}.log'.format(time.time()), level=logging.DEBUG)
  26 
  27     # start_t = time.time()
  28 
  29     func_name = func.__name__
  30 
  31     partial_cmdline = None
  32 
  33     # Try to run the func to compose the commandline
  34     try:
  35         # Execute the func to get the commandline
  36         partial_cmdline = func(*args, **kwargs)
  37         # Reformat the commandline with current args and kwargs
  38         executable = partial_cmdline.format(*args, **kwargs)
  39 
  40     except AttributeError as e:
  41         if partial_cmdline is not None:
  42             raise pe.AppBadFormatting("App formatting failed for app '{}' with AttributeError: {}".format(func_name, e))
  43         else:
  44             raise pe.BashAppNoReturn("Bash app '{}' did not return a value, or returned none - with this exception: {}".format(func_name, e), None)
  45 
  46     except IndexError as e:
  47         raise pe.AppBadFormatting("App formatting failed for app '{}' with IndexError: {}".format(func_name, e))
  48     except Exception as e:
  49         logging.error("Caught exception during formatting of app '{}': {}".format(func_name, e))
  50         raise e
  51 
  52     logging.debug("Executable: %s", executable)
  53 
  54     # Updating stdout, stderr if values passed at call time.
  55 
  56     def open_std_fd(fdname):
  57         # fdname is 'stdout' or 'stderr'
  58         stdfspec = kwargs.get(fdname)  # spec is str name or tuple (name, mode)
  59         if stdfspec is None:
  60             return None
  61         elif isinstance(stdfspec, str):
  62             fname = stdfspec
  63             mode = 'a+'
  64         elif isinstance(stdfspec, tuple):
  65             if len(stdfspec) != 2:
  66                 raise pe.BadStdStreamFile("std descriptor %s has incorrect tuple length %s" % (fdname, len(stdfspec)), TypeError('Bad Tuple Length'))
  67             fname, mode = stdfspec
  68         else:
  69             raise pe.BadStdStreamFile("std descriptor %s has unexpected type %s" % (fdname, str(type(stdfspec))), TypeError('Bad Tuple Type'))
  70         try:
  71             fd = open(fname, mode)
  72         except Exception as e:
  73             raise pe.BadStdStreamFile(fname, e)
  74         return fd
  75 
  76     std_out = open_std_fd('stdout')
  77     std_err = open_std_fd('stderr')
  78     timeout = kwargs.get('walltime')
  79 
  80     returncode = None
  81     try:
  82         proc = subprocess.Popen(executable, stdout=std_out, stderr=std_err, shell=True, executable='/bin/bash')
  83         proc.wait(timeout=timeout)
  84         returncode = proc.returncode
  85 
  86     except subprocess.TimeoutExpired:
  87         # print("Timeout")
  88         raise pe.AppTimeout("[{}] App exceeded walltime: {}".format(func_name, timeout))
  89 
  90     except Exception as e:
  91         # print("Caught exception: ", e)
  92         raise pe.AppException("[{}] App caught exception: {}".format(func_name, proc.returncode), e)
  93 
  94     if returncode != 0:
  95         raise pe.AppFailure("[{}] App failed with exit code: {}".format(func_name, proc.returncode), proc.returncode)
  96 
  97     # TODO : Add support for globs here
  98 
  99     missing = []
  100     for outputfile in kwargs.get('outputs', []):
  101         fpath = outputfile
  102         if type(outputfile) != str:
  103             fpath = outputfile.filepath
  104 
  105         if not os.path.exists(fpath):
  106             missing.extend([outputfile])
  107 
  108     if missing:
  109         raise pe.MissingOutputs("[{}] Missing outputs".format(func_name), missing)
  110 
  111     # exec_duration = time.time() - start_t
  112     return returncode
  113 
  114 
  115 class BashApp(AppBase):
  116 
  117     def __init__(self, func, data_flow_kernel=None, walltime=60, cache=False, executors='all'):
  118         super().__init__(func, data_flow_kernel=data_flow_kernel, walltime=60, executors=executors, cache=cache)
  119         self.kwargs = {}
  120 
  121         # We duplicate the extraction of parameter defaults
  122         # to self.kwargs to ensure availability at point of
  123         # command string format. Refer: #349
  124         sig = signature(func)
  125 
  126         for s in sig.parameters:
  127             if sig.parameters[s].default != Parameter.empty:
  128                 self.kwargs[s] = sig.parameters[s].default
  129 
  130     def __call__(self, *args, **kwargs):
  131         """Handle the call to a Bash app.
  132 
  133         Args:
  134              - Arbitrary
  135 
  136         Kwargs:
  137              - Arbitrary
  138 
  139         Returns:
  140              If outputs=[...] was a kwarg then:
  141                    App_fut, [Data_Futures...]
  142              else:
  143                    App_fut
  144 
  145         """
  146         # Update kwargs in the app definition with ones passed in at calltime
  147         self.kwargs.update(kwargs)
  148 
  149         if self.data_flow_kernel is None:
  150             dfk = DataFlowKernelLoader.dfk()
  151         else:
  152             dfk = self.data_flow_kernel
  153 
  154         app_fut = dfk.submit(wrap_error(update_wrapper(remote_side_bash_executor, self.func)),
  155                              self.func, *args,
  156                              executors=self.executors,
  157                              fn_hash=self.func_hash,
  158                              cache=self.cache,
  159                              **self.kwargs)
  160 
  161         out_futs = [DataFuture(app_fut, o, tid=app_fut.tid)
  162                     for o in kwargs.get('outputs', [])]
  163         app_fut._outputs = out_futs
  164 
  165         return app_fut
  166
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/parsl/app/bash.py b/parsl/app/bash.py
  --- a/parsl/app/bash.py
  +++ b/parsl/app/bash.py
  @@ -77,6 +77,9 @@
       std_err = open_std_fd('stderr')
       timeout = kwargs.get('walltime')
   
  +    if std_err is not None:
  +        print('--> executable follows <--\n{}\n--> end executable <--'.format(executable), file=std_err)
  +
       returncode = None
       try:
           proc = subprocess.Popen(executable, stdout=std_out, stderr=std_err, shell=True, executable='/bin/bash')
  
verification_info: {"golden_diff": "diff --git a/parsl/app/bash.py b/parsl/app/bash.py\n--- a/parsl/app/bash.py\n+++ b/parsl/app/bash.py\n@@ -77,6 +77,9 @@\n     std_err = open_std_fd('stderr')\n     timeout = kwargs.get('walltime')\n \n+    if std_err is not None:\n+        print('--> executable follows <--\\n{}\\n--> end executable <--'.format(executable), file=std_err)\n+\n     returncode = None\n     try:\n         proc = subprocess.Popen(executable, stdout=std_out, stderr=std_err, shell=True, executable='/bin/bash')\n", "issue": "Log app args\nFor easier debugging, we should log the arguments apps are called with.\r\n\r\nRequested by @mjwilde \n", "before_files": [{"content": "import logging\nfrom functools import update_wrapper\nfrom inspect import signature, Parameter\n\nfrom parsl.app.errors import wrap_error\nfrom parsl.app.futures import DataFuture\nfrom parsl.app.app import AppBase\nfrom parsl.dataflow.dflow import DataFlowKernelLoader\n\nlogger = logging.getLogger(__name__)\n\n\ndef remote_side_bash_executor(func, *args, **kwargs):\n    \"\"\"Execute the bash app type function and return the command line string.\n\n    This string is reformatted with the *args, and **kwargs\n    from call time.\n    \"\"\"\n    import os\n    import time\n    import subprocess\n    import logging\n    import parsl.app.errors as pe\n\n    logging.basicConfig(filename='/tmp/bashexec.{0}.log'.format(time.time()), level=logging.DEBUG)\n\n    # start_t = time.time()\n\n    func_name = func.__name__\n\n    partial_cmdline = None\n\n    # Try to run the func to compose the commandline\n    try:\n        # Execute the func to get the commandline\n        partial_cmdline = func(*args, **kwargs)\n        # Reformat the commandline with current args and kwargs\n        executable = partial_cmdline.format(*args, **kwargs)\n\n    except AttributeError as e:\n        if partial_cmdline is not None:\n            raise pe.AppBadFormatting(\"App formatting failed for app '{}' with AttributeError: {}\".format(func_name, e))\n        else:\n            raise pe.BashAppNoReturn(\"Bash app '{}' did not return a value, or returned none - with this exception: {}\".format(func_name, e), None)\n\n    except IndexError as e:\n        raise pe.AppBadFormatting(\"App formatting failed for app '{}' with IndexError: {}\".format(func_name, e))\n    except Exception as e:\n        logging.error(\"Caught exception during formatting of app '{}': {}\".format(func_name, e))\n        raise e\n\n    logging.debug(\"Executable: %s\", executable)\n\n    # Updating stdout, stderr if values passed at call time.\n\n    def open_std_fd(fdname):\n        # fdname is 'stdout' or 'stderr'\n        stdfspec = kwargs.get(fdname)  # spec is str name or tuple (name, mode)\n        if stdfspec is None:\n            return None\n        elif isinstance(stdfspec, str):\n            fname = stdfspec\n            mode = 'a+'\n        elif isinstance(stdfspec, tuple):\n            if len(stdfspec) != 2:\n                raise pe.BadStdStreamFile(\"std descriptor %s has incorrect tuple length %s\" % (fdname, len(stdfspec)), TypeError('Bad Tuple Length'))\n            fname, mode = stdfspec\n        else:\n            raise pe.BadStdStreamFile(\"std descriptor %s has unexpected type %s\" % (fdname, str(type(stdfspec))), TypeError('Bad Tuple Type'))\n        try:\n            fd = open(fname, mode)\n        except Exception as e:\n            raise pe.BadStdStreamFile(fname, e)\n        return fd\n\n    std_out = open_std_fd('stdout')\n    std_err = open_std_fd('stderr')\n    timeout = kwargs.get('walltime')\n\n    returncode = None\n    try:\n        proc = subprocess.Popen(executable, stdout=std_out, stderr=std_err, shell=True, executable='/bin/bash')\n        proc.wait(timeout=timeout)\n        returncode = proc.returncode\n\n    except subprocess.TimeoutExpired:\n        # print(\"Timeout\")\n        raise pe.AppTimeout(\"[{}] App exceeded walltime: {}\".format(func_name, timeout))\n\n    except Exception as e:\n        # print(\"Caught exception: \", e)\n        raise pe.AppException(\"[{}] App caught exception: {}\".format(func_name, proc.returncode), e)\n\n    if returncode != 0:\n        raise pe.AppFailure(\"[{}] App failed with exit code: {}\".format(func_name, proc.returncode), proc.returncode)\n\n    # TODO : Add support for globs here\n\n    missing = []\n    for outputfile in kwargs.get('outputs', []):\n        fpath = outputfile\n        if type(outputfile) != str:\n            fpath = outputfile.filepath\n\n        if not os.path.exists(fpath):\n            missing.extend([outputfile])\n\n    if missing:\n        raise pe.MissingOutputs(\"[{}] Missing outputs\".format(func_name), missing)\n\n    # exec_duration = time.time() - start_t\n    return returncode\n\n\nclass BashApp(AppBase):\n\n    def __init__(self, func, data_flow_kernel=None, walltime=60, cache=False, executors='all'):\n        super().__init__(func, data_flow_kernel=data_flow_kernel, walltime=60, executors=executors, cache=cache)\n        self.kwargs = {}\n\n        # We duplicate the extraction of parameter defaults\n        # to self.kwargs to ensure availability at point of\n        # command string format. Refer: #349\n        sig = signature(func)\n\n        for s in sig.parameters:\n            if sig.parameters[s].default != Parameter.empty:\n                self.kwargs[s] = sig.parameters[s].default\n\n    def __call__(self, *args, **kwargs):\n        \"\"\"Handle the call to a Bash app.\n\n        Args:\n             - Arbitrary\n\n        Kwargs:\n             - Arbitrary\n\n        Returns:\n             If outputs=[...] was a kwarg then:\n                   App_fut, [Data_Futures...]\n             else:\n                   App_fut\n\n        \"\"\"\n        # Update kwargs in the app definition with ones passed in at calltime\n        self.kwargs.update(kwargs)\n\n        if self.data_flow_kernel is None:\n            dfk = DataFlowKernelLoader.dfk()\n        else:\n            dfk = self.data_flow_kernel\n\n        app_fut = dfk.submit(wrap_error(update_wrapper(remote_side_bash_executor, self.func)),\n                             self.func, *args,\n                             executors=self.executors,\n                             fn_hash=self.func_hash,\n                             cache=self.cache,\n                             **self.kwargs)\n\n        out_futs = [DataFuture(app_fut, o, tid=app_fut.tid)\n                    for o in kwargs.get('outputs', [])]\n        app_fut._outputs = out_futs\n\n        return app_fut\n", "path": "parsl/app/bash.py"}], "after_files": [{"content": "import logging\nfrom functools import update_wrapper\nfrom inspect import signature, Parameter\n\nfrom parsl.app.errors import wrap_error\nfrom parsl.app.futures import DataFuture\nfrom parsl.app.app import AppBase\nfrom parsl.dataflow.dflow import DataFlowKernelLoader\n\nlogger = logging.getLogger(__name__)\n\n\ndef remote_side_bash_executor(func, *args, **kwargs):\n    \"\"\"Execute the bash app type function and return the command line string.\n\n    This string is reformatted with the *args, and **kwargs\n    from call time.\n    \"\"\"\n    import os\n    import time\n    import subprocess\n    import logging\n    import parsl.app.errors as pe\n\n    logging.basicConfig(filename='/tmp/bashexec.{0}.log'.format(time.time()), level=logging.DEBUG)\n\n    # start_t = time.time()\n\n    func_name = func.__name__\n\n    partial_cmdline = None\n\n    # Try to run the func to compose the commandline\n    try:\n        # Execute the func to get the commandline\n        partial_cmdline = func(*args, **kwargs)\n        # Reformat the commandline with current args and kwargs\n        executable = partial_cmdline.format(*args, **kwargs)\n\n    except AttributeError as e:\n        if partial_cmdline is not None:\n            raise pe.AppBadFormatting(\"App formatting failed for app '{}' with AttributeError: {}\".format(func_name, e))\n        else:\n            raise pe.BashAppNoReturn(\"Bash app '{}' did not return a value, or returned none - with this exception: {}\".format(func_name, e), None)\n\n    except IndexError as e:\n        raise pe.AppBadFormatting(\"App formatting failed for app '{}' with IndexError: {}\".format(func_name, e))\n    except Exception as e:\n        logging.error(\"Caught exception during formatting of app '{}': {}\".format(func_name, e))\n        raise e\n\n    logging.debug(\"Executable: %s\", executable)\n\n    # Updating stdout, stderr if values passed at call time.\n\n    def open_std_fd(fdname):\n        # fdname is 'stdout' or 'stderr'\n        stdfspec = kwargs.get(fdname)  # spec is str name or tuple (name, mode)\n        if stdfspec is None:\n            return None\n        elif isinstance(stdfspec, str):\n            fname = stdfspec\n            mode = 'a+'\n        elif isinstance(stdfspec, tuple):\n            if len(stdfspec) != 2:\n                raise pe.BadStdStreamFile(\"std descriptor %s has incorrect tuple length %s\" % (fdname, len(stdfspec)), TypeError('Bad Tuple Length'))\n            fname, mode = stdfspec\n        else:\n            raise pe.BadStdStreamFile(\"std descriptor %s has unexpected type %s\" % (fdname, str(type(stdfspec))), TypeError('Bad Tuple Type'))\n        try:\n            fd = open(fname, mode)\n        except Exception as e:\n            raise pe.BadStdStreamFile(fname, e)\n        return fd\n\n    std_out = open_std_fd('stdout')\n    std_err = open_std_fd('stderr')\n    timeout = kwargs.get('walltime')\n\n    if std_err is not None:\n        print('--> executable follows <--\\n{}\\n--> end executable <--'.format(executable), file=std_err)\n\n    returncode = None\n    try:\n        proc = subprocess.Popen(executable, stdout=std_out, stderr=std_err, shell=True, executable='/bin/bash')\n        proc.wait(timeout=timeout)\n        returncode = proc.returncode\n\n    except subprocess.TimeoutExpired:\n        # print(\"Timeout\")\n        raise pe.AppTimeout(\"[{}] App exceeded walltime: {}\".format(func_name, timeout))\n\n    except Exception as e:\n        # print(\"Caught exception: \", e)\n        raise pe.AppException(\"[{}] App caught exception: {}\".format(func_name, proc.returncode), e)\n\n    if returncode != 0:\n        raise pe.AppFailure(\"[{}] App failed with exit code: {}\".format(func_name, proc.returncode), proc.returncode)\n\n    # TODO : Add support for globs here\n\n    missing = []\n    for outputfile in kwargs.get('outputs', []):\n        fpath = outputfile\n        if type(outputfile) != str:\n            fpath = outputfile.filepath\n\n        if not os.path.exists(fpath):\n            missing.extend([outputfile])\n\n    if missing:\n        raise pe.MissingOutputs(\"[{}] Missing outputs\".format(func_name), missing)\n\n    # exec_duration = time.time() - start_t\n    return returncode\n\n\nclass BashApp(AppBase):\n\n    def __init__(self, func, data_flow_kernel=None, walltime=60, cache=False, executors='all'):\n        super().__init__(func, data_flow_kernel=data_flow_kernel, walltime=60, executors=executors, cache=cache)\n        self.kwargs = {}\n\n        # We duplicate the extraction of parameter defaults\n        # to self.kwargs to ensure availability at point of\n        # command string format. Refer: #349\n        sig = signature(func)\n\n        for s in sig.parameters:\n            if sig.parameters[s].default != Parameter.empty:\n                self.kwargs[s] = sig.parameters[s].default\n\n    def __call__(self, *args, **kwargs):\n        \"\"\"Handle the call to a Bash app.\n\n        Args:\n             - Arbitrary\n\n        Kwargs:\n             - Arbitrary\n\n        Returns:\n             If outputs=[...] was a kwarg then:\n                   App_fut, [Data_Futures...]\n             else:\n                   App_fut\n\n        \"\"\"\n        # Update kwargs in the app definition with ones passed in at calltime\n        self.kwargs.update(kwargs)\n\n        if self.data_flow_kernel is None:\n            dfk = DataFlowKernelLoader.dfk()\n        else:\n            dfk = self.data_flow_kernel\n\n        app_fut = dfk.submit(wrap_error(update_wrapper(remote_side_bash_executor, self.func)),\n                             self.func, *args,\n                             executors=self.executors,\n                             fn_hash=self.func_hash,\n                             cache=self.cache,\n                             **self.kwargs)\n\n        out_futs = [DataFuture(app_fut, o, tid=app_fut.tid)\n                    for o in kwargs.get('outputs', [])]\n        app_fut._outputs = out_futs\n\n        return app_fut\n", "path": "parsl/app/bash.py"}]}