host: check reply_fds before sending them
If there are fds to send back to the client, do a check that none of them are invalid, so that we do not raise an exception in send later. This allows us to send a proper RemoteError instead of no reply at all.
This commit is contained in:
parent
6a39067772
commit
28dcd0ee9a
1 changed files with 18 additions and 2 deletions
|
|
@ -38,6 +38,7 @@ their clean up, independent of any control of osbuild.
|
||||||
import abc
|
import abc
|
||||||
import argparse
|
import argparse
|
||||||
import asyncio
|
import asyncio
|
||||||
|
import fcntl
|
||||||
import importlib
|
import importlib
|
||||||
import io
|
import io
|
||||||
import os
|
import os
|
||||||
|
|
@ -252,11 +253,17 @@ class Service(abc.ABC):
|
||||||
if not msg:
|
if not msg:
|
||||||
break
|
break
|
||||||
|
|
||||||
|
reply_fds = None
|
||||||
try:
|
try:
|
||||||
reply, reply_fds = self._handle_message(msg, fds)
|
reply, reply_fds = self._handle_message(msg, fds)
|
||||||
|
|
||||||
|
# Catch invalid file descriptors early so that
|
||||||
|
# we send an error reply instead of throwing
|
||||||
|
# an exception in `sock.send` later.
|
||||||
|
self._check_fds(reply_fds)
|
||||||
|
|
||||||
except: # pylint: disable=bare-except
|
except: # pylint: disable=bare-except
|
||||||
reply_fds = None
|
reply_fds = self._close_all(reply_fds)
|
||||||
_, val, tb = sys.exc_info()
|
_, val, tb = sys.exc_info()
|
||||||
reply = self.protocol.encode_exception(val, tb)
|
reply = self.protocol.encode_exception(val, tb)
|
||||||
|
|
||||||
|
|
@ -289,13 +296,22 @@ class Service(abc.ABC):
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def _close_all(fds: Optional[List[int]]):
|
def _close_all(fds: Optional[List[int]]):
|
||||||
if not fds:
|
if not fds:
|
||||||
return
|
return []
|
||||||
|
|
||||||
for fd in fds:
|
for fd in fds:
|
||||||
try:
|
try:
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
except OSError as e:
|
except OSError as e:
|
||||||
print(f"error closing fd '{fd}': {e!s}")
|
print(f"error closing fd '{fd}': {e!s}")
|
||||||
|
return []
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def _check_fds(fds: Optional[List[int]]):
|
||||||
|
if not fds:
|
||||||
|
return
|
||||||
|
|
||||||
|
for fd in fds:
|
||||||
|
fcntl.fcntl(fd, fcntl.F_GETFD)
|
||||||
|
|
||||||
|
|
||||||
class ServiceClient:
|
class ServiceClient:
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue