Skip to content

Commit

Permalink
Fix AttributeError: 'NoneType' object has no attribute 'write'
Browse files Browse the repository at this point in the history
Apport can fail with:

```
Traceback (most recent call last):
  File "/usr/share/apport/apport", line 531, in <module>
    options = parse_arguments()
  File "/usr/share/apport/apport", line 463, in parse_arguments
    parser.print_usage()
  File "/usr/lib/python3.9/argparse.py", line 2557, in print_usage
    self._print_message(self.format_usage(), file)
  File "/usr/lib/python3.9/argparse.py", line 2568, in _print_message
    file.write(message)
AttributeError: 'NoneType' object has no attribute 'write'
```

The kernel calls apport with no stdout and stderr file descriptors set.
Therefore `sys.stdout` and `sys.stderr` are `None`.

So initialize the error log before parsing the command line arguments.
Also improve the error message when no process ID (PID) is provided.

Bug: https://launchpad.net/bugs/1979211
Fixes: c320e91 ("Switch to using non-positional arguments")
Signed-off-by: Benjamin Drung <bdrung@ubuntu.com>
  • Loading branch information
bdrung committed Jun 22, 2022
1 parent e0a9052 commit 6bdf317
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 3 deletions.
7 changes: 4 additions & 3 deletions data/apport
Expand Up @@ -551,7 +551,9 @@ def parse_arguments():
)

if options.pid is None:
parser.print_usage()
parser.error(
"No process ID (PID) provided. Please specify PID with -p/--pid."
)
sys.exit(1)

for arg in rest:
Expand Down Expand Up @@ -634,9 +636,8 @@ if "LISTEN_FDS" in os.environ:
sys.exit(1)


options = parse_arguments()

init_error_log()
options = parse_arguments()

# Check if we received a valid global PID (kernel >= 3.12). If we do,
# then compare it with the local PID. If they don't match, it's an
Expand Down
25 changes: 25 additions & 0 deletions tests/integration/test_signal_crashes.py
Expand Up @@ -295,6 +295,31 @@ def test_unpackaged_script(self):
self.do_crash(command="./myscript")
self.assertEqual(apport.fileutils.get_all_reports(), [])

def test_unsupported_arguments_no_stderr(self):
"""Write failure to log file when stderr is missing
The kernel calls apport with no stdout and stderr file
descriptors set.
"""

def close_stdin_and_stderr():
"""Close stdin and stderr"""
os.close(sys.stdout.fileno())
os.close(sys.stderr.fileno())

log = os.path.join(self.workdir, "apport.log")
env = os.environ.copy()
env["APPORT_LOG_FILE"] = log
app = subprocess.run(
[self.apport_path], env=env, preexec_fn=close_stdin_and_stderr
)

self.assertEqual(app.returncode, 2)
with open(log) as log_file:
logged = log_file.read()
self.assertIn("usage", logged)
self.assertIn("error: No process ID (PID) provided", logged)

def test_ignore_sigquit(self):
"""apport ignores SIGQUIT"""

Expand Down

0 comments on commit 6bdf317

Please sign in to comment.