Repository: certbot/certbot

Issue:
Reduce "During handling of the above exception, another exception occurred" CLI output
Sometimes when encountering exceptions, Certbot outputs multiple stack traces on the CLI which are almost identical.

These take up a lot of room, and make any other important output hard to read. 

As part of the terminal output revamp, we should find a way to improve this so it is more compact and not so duplicative.

I am not sure if it is possible to tackle this in a generic way, or whether we would need to tackle specific instances where this has been a problem.

e.g:

    $ sudo certbot install --nginx --cert-name random27579.example.org
    Saving debug log to /var/log/letsencrypt/letsencrypt.log
    Plugins selected: Authenticator None, Installer nginx
    Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/default
    Deploying Certificate to VirtualHost /etc/nginx/sites-enabled/default
    Rolling back to previous server configuration...
    Encountered exception during recovery:
    Traceback (most recent call last):
      File "/home/alex/devel/certbot/certbot/certbot/_internal/client.py", line 530, in deploy_certificate
        self.installer.restart()
      File "/home/alex/devel/certbot/certbot-nginx/certbot_nginx/_internal/configurator.py", line 918, in restart
        nginx_restart(self.conf('ctl'), self.nginx_conf, self.conf('sleep-seconds'))
      File "/home/alex/devel/certbot/certbot-nginx/certbot_nginx/_internal/configurator.py", line 1199, in nginx_restart
        raise errors.MisconfigurationError(
    certbot.errors.MisconfigurationError: nginx restart failed:
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] still could not bind()


    During handling of the above exception, another exception occurred:

    Traceback (most recent call last):
      File "/home/alex/devel/certbot/certbot/certbot/_internal/error_handler.py", line 125, in _call_registered
        self.funcs[-1]()
      File "/home/alex/devel/certbot/certbot/certbot/_internal/client.py", line 630, in _rollback_and_restart
        self.installer.restart()
      File "/home/alex/devel/certbot/certbot-nginx/certbot_nginx/_internal/configurator.py", line 918, in restart
        nginx_restart(self.conf('ctl'), self.nginx_conf, self.conf('sleep-seconds'))
      File "/home/alex/devel/certbot/certbot-nginx/certbot_nginx/_internal/configurator.py", line 1199, in nginx_restart
        raise errors.MisconfigurationError(
    certbot.errors.MisconfigurationError: nginx restart failed:
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] still could not bind()

    nginx restart failed:
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] bind() to 0.0.0.0:80 failed (98: Address already in use)
    nginx: [emerg] still could not bind()


    IMPORTANT NOTES:
    - An error occurred and we failed to restore your config and restart
      your server. Please post to
      https://community.letsencrypt.org/c/help with details about your
      configuration and this error you received.


Discussion:
While I think putting this in the UX project was the most important thing, I'm going to throw this in the 1.9.0 milestone for now just so we can easily see it when looking at our current work.

Resolving patch:
diff --git a/certbot/certbot/_internal/error_handler.py b/certbot/certbot/_internal/error_handler.py
--- a/certbot/certbot/_internal/error_handler.py
+++ b/certbot/certbot/_internal/error_handler.py
@@ -123,8 +123,10 @@ def _call_registered(self):
         while self.funcs:
             try:
                 self.funcs[-1]()
-            except Exception:  # pylint: disable=broad-except
-                logger.error("Encountered exception during recovery: ", exc_info=True)
+            except Exception as exc:  # pylint: disable=broad-except
+                output = traceback.format_exception_only(type(exc), exc)
+                logger.error("Encountered exception during recovery: %s",
+                             ''.join(output).rstrip())
             self.funcs.pop()
 
     def _set_signal_handlers(self):


Test patch: