| Index: util/win/exception_handler_server.cc | 
| diff --git a/util/win/exception_handler_server.cc b/util/win/exception_handler_server.cc | 
| index 50daa39a92a2035c71f4395c7861a7eb2980c848..2035c57857cd0e98428d0f2a029e71fa0801e92c 100644 | 
| --- a/util/win/exception_handler_server.cc | 
| +++ b/util/win/exception_handler_server.cc | 
| @@ -35,6 +35,29 @@ namespace crashpad { | 
|  | 
| namespace { | 
|  | 
| +// We create two pipe instances, so that there's one listening while the | 
| +// PipeServiceProc is processing a registration. | 
| +const size_t kPipeInstances = 2; | 
| + | 
| +// Wraps CreateNamedPipe() to create a single named pipe instance. | 
| +// | 
| +// If first_instance is true, the named pipe instance will be created with | 
| +// FILE_FLAG_FIRST_PIPE_INSTANCE. This ensures that the the pipe name is not | 
| +// already in use when created. | 
| +HANDLE CreateNamedPipeInstance(const std::wstring& pipe_name, | 
| +                               bool first_instance) { | 
| +  return CreateNamedPipe(pipe_name.c_str(), | 
| +                         PIPE_ACCESS_DUPLEX | | 
| +                             (first_instance ? FILE_FLAG_FIRST_PIPE_INSTANCE | 
| +                                             : 0), | 
| +                         PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, | 
| +                         kPipeInstances, | 
| +                         512, | 
| +                         512, | 
| +                         0, | 
| +                         nullptr); | 
| +} | 
| + | 
| decltype(GetNamedPipeClientProcessId)* GetNamedPipeClientProcessIdFunction() { | 
| static const auto get_named_pipe_client_process_id = | 
| GET_FUNCTION(L"kernel32.dll", ::GetNamedPipeClientProcessId); | 
| @@ -234,10 +257,10 @@ class ClientData { | 
| ExceptionHandlerServer::Delegate::~Delegate() { | 
| } | 
|  | 
| -ExceptionHandlerServer::ExceptionHandlerServer(const std::string& pipe_name, | 
| -                                               bool persistent) | 
| -    : pipe_name_(pipe_name), | 
| +ExceptionHandlerServer::ExceptionHandlerServer(bool persistent) | 
| +    : pipe_name_(), | 
| port_(CreateIoCompletionPort(INVALID_HANDLE_VALUE, nullptr, 0, 1)), | 
| +      first_pipe_instance_(), | 
| clients_lock_(), | 
| clients_(), | 
| persistent_(persistent) { | 
| @@ -246,23 +269,59 @@ ExceptionHandlerServer::ExceptionHandlerServer(const std::string& pipe_name, | 
| ExceptionHandlerServer::~ExceptionHandlerServer() { | 
| } | 
|  | 
| +void ExceptionHandlerServer::SetPipeName(const std::wstring& pipe_name) { | 
| +  DCHECK(pipe_name_.empty()); | 
| +  DCHECK(!pipe_name.empty()); | 
| + | 
| +  pipe_name_ = pipe_name; | 
| +} | 
| + | 
| +std::wstring ExceptionHandlerServer::CreatePipe() { | 
| +  DCHECK(!first_pipe_instance_.is_valid()); | 
| + | 
| +  int tries = 5; | 
| +  std::string pipe_name_base = | 
| +      base::StringPrintf("\\\\.\\pipe\\crashpad_%d_", GetCurrentProcessId()); | 
| +  std::wstring pipe_name; | 
| +  do { | 
| +    pipe_name = base::UTF8ToUTF16(pipe_name_base); | 
| +    for (int index = 0; index < 16; ++index) { | 
| +      pipe_name.append(1, static_cast<wchar_t>(base::RandInt('A', 'Z'))); | 
| +    } | 
| + | 
| +    first_pipe_instance_.reset(CreateNamedPipeInstance(pipe_name, true)); | 
| + | 
| +    // CreateNamedPipe() is documented as setting the error to | 
| +    // ERROR_ACCESS_DENIED if FILE_FLAG_FIRST_PIPE_INSTANCE is specified and the | 
| +    // pipe name is already in use. However it may set the error to other codes | 
| +    // such as ERROR_PIPE_BUSY (if the pipe already exists and has reached its | 
| +    // maximum instance count) or ERROR_INVALID_PARAMETER (if the pipe already | 
| +    // exists and its attributes differ from those specified to | 
| +    // CreateNamedPipe()). Some of these errors may be ambiguous: for example, | 
| +    // ERROR_INVALID_PARAMETER may also occur if CreateNamedPipe() is called | 
| +    // incorrectly even in the absence of an existing pipe by the same name. | 
| +    // | 
| +    // Rather than chasing down all of the possible errors that might indicate | 
| +    // that a pipe name is already in use, retry up to a few times on any error. | 
| +  } while (!first_pipe_instance_.is_valid() && --tries); | 
| + | 
| +  PCHECK(first_pipe_instance_.is_valid()) << "CreateNamedPipe"; | 
| + | 
| +  SetPipeName(pipe_name); | 
| +  return pipe_name; | 
| +} | 
| + | 
| void ExceptionHandlerServer::Run(Delegate* delegate) { | 
| uint64_t shutdown_token = base::RandUint64(); | 
| -  // We create two pipe instances, so that there's one listening while the | 
| -  // PipeServiceProc is processing a registration. | 
| -  ScopedKernelHANDLE thread_handles[2]; | 
| -  base::string16 pipe_name_16(base::UTF8ToUTF16(pipe_name_)); | 
| +  ScopedKernelHANDLE thread_handles[kPipeInstances]; | 
| for (int i = 0; i < arraysize(thread_handles); ++i) { | 
| -    HANDLE pipe = | 
| -        CreateNamedPipe(pipe_name_16.c_str(), | 
| -                        PIPE_ACCESS_DUPLEX, | 
| -                        PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT, | 
| -                        arraysize(thread_handles), | 
| -                        512, | 
| -                        512, | 
| -                        0, | 
| -                        nullptr); | 
| -    PCHECK(pipe != INVALID_HANDLE_VALUE) << "CreateNamedPipe"; | 
| +    HANDLE pipe; | 
| +    if (first_pipe_instance_.is_valid()) { | 
| +      pipe = first_pipe_instance_.release(); | 
| +    } else { | 
| +      pipe = CreateNamedPipeInstance(pipe_name_, false); | 
| +      PCHECK(pipe != INVALID_HANDLE_VALUE) << "CreateNamedPipe"; | 
| +    } | 
|  | 
| // Ownership of this object (and the pipe instance) is given to the new | 
| // thread. We close the thread handles at the end of the scope. They clean | 
| @@ -313,7 +372,7 @@ void ExceptionHandlerServer::Run(Delegate* delegate) { | 
| message.type = ClientToServerMessage::kShutdown; | 
| message.shutdown.token = shutdown_token; | 
| ServerToClientMessage response; | 
| -    SendToCrashHandlerServer(pipe_name_16, | 
| +    SendToCrashHandlerServer(pipe_name_, | 
| reinterpret_cast<ClientToServerMessage&>(message), | 
| &response); | 
| } | 
|  |