| 202 | os.write(self.stdout_fd, msg) |
| 203 | |
| 204 | def serve(self): |
| 205 | def inner_serve(): |
| 206 | os.set_blocking(self.stdin_fd, False) |
| 207 | assert not os.get_blocking(self.stdin_fd) |
| 208 | os.set_blocking(self.stdout_fd, True) |
| 209 | assert os.get_blocking(self.stdout_fd) |
| 210 | |
| 211 | unpacker = get_limited_unpacker("server") |
| 212 | shutdown_serve = False |
| 213 | while True: |
| 214 | # before processing any new RPCs, send out all pending log output |
| 215 | self.send_queued_log() |
| 216 | |
| 217 | if shutdown_serve: |
| 218 | # shutdown wanted! get out of here after sending all log output. |
| 219 | assert self.repository is None |
| 220 | return |
| 221 | |
| 222 | # process new RPCs |
| 223 | r, w, es = select.select([self.stdin_fd], [], [], 10) |
| 224 | if r: |
| 225 | data = os.read(self.stdin_fd, BUFSIZE) |
| 226 | if not data: |
| 227 | shutdown_serve = True |
| 228 | continue |
| 229 | unpacker.feed(data) |
| 230 | for unpacked in unpacker: |
| 231 | if isinstance(unpacked, dict): |
| 232 | msgid = unpacked[MSGID] |
| 233 | method = unpacked[MSG] |
| 234 | args = unpacked[ARGS] |
| 235 | else: |
| 236 | if self.repository is not None: |
| 237 | self.repository.close() |
| 238 | raise UnexpectedRPCDataFormatFromClient(__version__) |
| 239 | try: |
| 240 | # logger.debug(f"{type(self)} method: {type(self.repository)}.{method}") |
| 241 | if method not in self.rpc_methods: |
| 242 | raise InvalidRPCMethod(method) |
| 243 | try: |
| 244 | f = getattr(self, method) |
| 245 | except AttributeError: |
| 246 | f = getattr(self.repository, method) |
| 247 | args = self.filter_args(f, args) |
| 248 | res = f(**args) |
| 249 | except BaseException as e: |
| 250 | # These exceptions are reconstructed on the client end in RemoteRepository.call_many(), |
| 251 | # and will be handled just like locally raised exceptions. Suppress the remote traceback |
| 252 | # for these, except ErrorWithTraceback, which should always display a traceback. |
| 253 | reconstructed_exceptions = ( |
| 254 | Repository.InvalidRepository, |
| 255 | Repository.InvalidRepositoryConfig, |
| 256 | Repository.DoesNotExist, |
| 257 | Repository.AlreadyExists, |
| 258 | Repository.PathAlreadyExists, |
| 259 | PathNotAllowed, |
| 260 | Repository.InsufficientFreeSpaceError, |
| 261 | ) |