This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: logging.handlers.SysLogHandler doesn't get cleaned up properly on exit if it throws an exception
Type: behavior Stage:
Components: Library (Lib) Versions: Python 3.9
process
Status: open Resolution:
Dependencies: Superseder:
Assigned To: Nosy List: gstarck, ngie, vinay.sajip
Priority: normal Keywords:

Created on 2022-03-29 23:56 by ngie, last changed 2022-04-11 14:59 by admin.

Messages (8)
msg416309 - (view) Author: Enji Cooper (ngie) * Date: 2022-03-29 23:56
Something I noticed when trying to repro another issue:

% python
Python 3.8.13 (default, Mar 16 2022, 17:28:59)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import logging.handlers
>>> logging.handlers.SysLogHandler(address=("something-completely-bogus-doncha-know", 514))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.8/logging/handlers.py", line 829, in __init__
    ress = socket.getaddrinfo(host, port, 0, socktype)
  File "/usr/lib/python3.8/socket.py", line 918, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known
>>>
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python3.8/logging/__init__.py", line 2127, in shutdown
    h.close()
  File "/usr/lib/python3.8/logging/handlers.py", line 892, in close
    self.socket.close()
AttributeError: 'SysLogHandler' object has no attribute 'socket'
% python3.9
Python 3.9.11 (main, Mar 16 2022, 17:27:06)
[GCC 7.5.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import logging.handlers
>>> logging.handlers.SysLogHandler(address=("something-completely-bogus-doncha-know", 514))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.9/logging/handlers.py", line 873, in __init__
    ress = socket.getaddrinfo(host, port, 0, socktype)
  File "/usr/lib/python3.9/socket.py", line 954, in getaddrinfo
    for res in _socket.getaddrinfo(host, port, family, type, proto, flags):
socket.gaierror: [Errno -2] Name or service not known
>>>
Error in atexit._run_exitfuncs:
Traceback (most recent call last):
  File "/usr/lib/python3.9/logging/__init__.py", line 2142, in shutdown
    h.close()
  File "/usr/lib/python3.9/logging/handlers.py", line 936, in close
    self.socket.close()
AttributeError: 'SysLogHandler' object has no attribute 'socket'

This is happening because logging.Handler is calling logging._addHandlerRef in logging.Handler.__init__ and _removeHandlerRef at exit via logging.shutdown(..).
msg416317 - (view) Author: Grégory Starck (gstarck) * Date: 2022-03-30 01:55
I think this is fixed in main, thanks to this:

https://github.com/python/cpython/blob/main/Lib/logging/handlers.py#L862-L863
msg416318 - (view) Author: Enji Cooper (ngie) * Date: 2022-03-30 02:07
Yup! Looks like it! Just needs a back port.
msg416344 - (view) Author: Grégory Starck (gstarck) * Date: 2022-03-30 12:11
I guess it could be done relatively easily.

but the question is more: should it be done ?
msg416413 - (view) Author: Enji Cooper (ngie) * Date: 2022-03-31 01:51
Grégory: good question.

I would personally advocate for doing it out of selfish interests. 

I'm working with middleware based on 3.8 (moving to 3.9+ is non-trivial), and we have a common fault scenario where the system breaks if logging.handlers.SysLogHandler is instantiated and the target host cannot be resolved, like seen in the first comment.

Backporting the changes you referenced would make addressing the above issue easier, since the logic in connect(..) was moved into its own routine.
msg416427 - (view) Author: Vinay Sajip (vinay.sajip) * (Python committer) Date: 2022-03-31 10:40
The 3.8 branch is security-fix-only now, I'm afraid. And I'm not sure it's worth backporting this.
msg416430 - (view) Author: Grégory Starck (gstarck) * Date: 2022-03-31 12:31
Enji : you can use this then:

```
In [6]: class Fixed(logging.handlers.SysLogHandler):
   ...:     def __init__(self, *a, **kw):
   ...:         self.socket = None
   ...:         super().__init__(*a, **kw)
   ...:     def close(self):
   ...:         if self.socket is None:
   ...:             return
   ...:         super().close()
```

that looks to be enough to prevent the issue.
msg416441 - (view) Author: Enji Cooper (ngie) * Date: 2022-03-31 15:30
Grégory: that will fix this issue, but what I really need is some of the other changes, like moving the getaddrinfo logic into a separate route (connect).
History
Date User Action Args
2022-04-11 14:59:57adminsetgithub: 91314
2022-03-31 15:30:09ngiesetmessages: + msg416441
2022-03-31 12:31:06gstarcksetmessages: + msg416430
2022-03-31 10:40:48vinay.sajipsetmessages: + msg416427
versions: - Python 3.8
2022-03-31 01:51:39ngiesetmessages: + msg416413
2022-03-31 00:30:04ned.deilysetnosy: + vinay.sajip
2022-03-30 12:11:45gstarcksetmessages: + msg416344
2022-03-30 02:07:52ngiesetmessages: + msg416318
2022-03-30 01:55:07gstarcksetnosy: + gstarck
messages: + msg416317
2022-03-29 23:56:50ngiecreate