Index: util/win/registration_protocol_win.cc |
diff --git a/util/win/registration_protocol_win.cc b/util/win/registration_protocol_win.cc |
index 38b1b45195a6b86f2353da09e1da04e8f5f9252d..af7f522508cdcdfc9c9c9f2653b0afc3b6e94b10 100644 |
--- a/util/win/registration_protocol_win.cc |
+++ b/util/win/registration_protocol_win.cc |
@@ -24,8 +24,14 @@ namespace crashpad { |
bool SendToCrashHandlerServer(const base::string16& pipe_name, |
const crashpad::ClientToServerMessage& message, |
crashpad::ServerToClientMessage* response) { |
- int tries = 0; |
- for (;;) { |
+ // Retry CreateFile() in a loop. If the handler isn’t actively waiting in |
+ // ConnectNamedPipe() on a pipe instance because it’s busy doing something |
+ // else, CreateFile() will fail with ERROR_PIPE_BUSY. WaitNamedPipe() waits |
+ // until a pipe instance is ready, but there’s no way to wait for this |
+ // condition and atomically open the client side of the pipe in a single |
+ // operation. CallNamedPipe() implements similar retry logic to this, also in |
+ // user-mode code. |
scottmg
2015/11/10 20:02:20
You could maybe also note that this means we don't
Mark Mentovai
2015/11/10 20:12:19
scottmg wrote:
|
+ for (int tries = 0;;) { |
ScopedFileHANDLE pipe( |
CreateFile(pipe_name.c_str(), |
GENERIC_READ | GENERIC_WRITE, |
@@ -65,12 +71,12 @@ bool SendToCrashHandlerServer(const base::string16& pipe_name, |
&bytes_read, |
nullptr); |
if (!result) { |
- LOG(ERROR) << "TransactNamedPipe: expected " << sizeof(*response) |
scottmg
2015/11/10 20:02:19
Duh, oops.
|
- << ", observed " << bytes_read; |
+ PLOG(ERROR) << "TransactNamedPipe"; |
return false; |
} |
if (bytes_read != sizeof(*response)) { |
- LOG(ERROR) << "TransactNamedPipe read incorrect number of bytes"; |
+ LOG(ERROR) << "TransactNamedPipe: expected " << sizeof(*response) |
+ << ", observed " << bytes_read; |
return false; |
} |
return true; |