haiwen / seafile-client

Seafile desktop client.
http://seafile.com
Apache License 2.0
469 stars 280 forks source link

Failed to connect to named pipe: All pipe instances are busy #1439

Closed DymOK93 closed 1 year ago

DymOK93 commented 1 year ago

The problem arises from a race condition between the creation of two named pipe instances in SeafileRpcClient::connectDaemon() and the creation of the daemon thread.

  1. Client creates a pipe instance for kSeafileRpcService.
  2. The daemon main worker is trying to spawns a new thread and may stuck in the kernel for some considerable time (for example, due to antivirus or EDR activity, or simply under heavy load)
  3. The client sees that the connection is successful and creates a second instance of the same pipe for kSeafileThreadedRpcService.
  4. If the time the worker daemon spends in the kernel exceeds 1-2ms (experimental), the client is very likely to get ERROR_PIPE_BUSY from CreateFile().
  5. In this case, the client writes to the log "Failed to connect to named pipe: All pipe instances are busy." and closes the instance from p.1.
  6. Now daemon has spawned a new thread and trying to read the pipe, but pipe is already closed.
  7. pipe_read_n() returns 0 for ERROR_BROKEN_PIPE so the daemon thread silently terminates. Then the situation repeats up to 20 * 16 times in total, after which the client exits with an error.

The bug was already mentioned (but not actually fixed) in https://github.com/haiwen/seafile-client/issues/1284.

My solution is similar to the Named Pipe Client example on the Microsoft website: using WaitNamedPipe() if CreateFile() fails with ERROR_PIPE_BUSY.

killing commented 1 year ago

Thank you for the nice patch! It's been merged.