Overlapped Pipe



  • Hi!

    Ich hab ein Problem mit Named Pipes im Overlapped-Modus. Mein Pipe-Server arbeitet beim ersten Durchlauf (Client verbindet sich, sendet Daten und Client trennt sich wieder) richtig. Wenn ich anschließend aber mich wieder verbinde, scheitert ReadFileEx() mit dem Fehler ERROR_PIPE_LISTENING. Woran kann das liegen?

    struct context_type {
    	OVERLAPPED overlapped;
    	HANDLE pipe;
    	std::vector<std::uint8_t> buffer;
    
    	context_type() {
    		std::memset(&overlapped, 0, sizeof overlapped);
    	}
    };
    
    ...
    void pipe_end::listen() {
    	listen_thread_.swap(std::thread([=]() {
    		OVERLAPPED overlapped = { 0 };
    		overlapped.hEvent = event_;
    		try {
    			for (;;) {
    				HANDLE pipe = CreateNamedPipe(L"\\\\.\\pipe\\neoee", FILE_FLAG_OVERLAPPED | PIPE_ACCESS_DUPLEX,
    					PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_ACCEPT_REMOTE_CLIENTS,
    					PIPE_UNLIMITED_INSTANCES, buffer_size_, buffer_size_, 0, 0);
    				if (pipe == 0 || pipe == INVALID_HANDLE_VALUE)
    					throw std::runtime_error("could not initialize named control pipe");
    
    				if (ConnectNamedPipe(pipe, &overlapped) == 0) {
    					switch (GetLastError()) {
    					case ERROR_IO_PENDING:
    					{
    						auto result = WaitForSingleObjectEx(overlapped.hEvent, INFINITE, TRUE);
    						if (result == FAIT_FAILED)
    							throw std::runtime_error("pipe waiting mode failure");
    						else if (result == WAIT_IO_COMPLETION)
    							break;
    						if (signaled_) return;
    					}
    					case ERROR_PIPE_CONNECTED:
    					{
    						context_type* context = new context_type;
    						context->pipe = pipe;
    						context->buffer.resize(buffer_size_);
    
    						// SCHEITERT BEIM ZWEITEN MAL!
    						if (ReadFileEx(context->pipe, &context->buffer[0], static_cast<DWORD>(context->buffer.size()),
    								reinterpret_cast<OVERLAPPED*>(&context->overlapped), &pipe_end::completion_routine) == FALSE) {
    								delete context;
    								DisconnectNamedPipe(context->pipe);
    								CloseHandle(context->pipe);
    								throw std::runtime_error("reading pipe error");
    						}
    					}
    					break;
    					default:
    						CloseHandle(pipe);
    						throw std::runtime_error("pipe connection failure");
    					}
    				}
    				else {
    					throw std::runtime_error("ConnectNamedPipe failure");
    				}
    			}
    		}
    		catch (const std::runtime_error& error) {
    			std::cerr << "Pipe exception: " << error.what() << std::endl;
    		}
    	}));
    }
    
    void WINAPI pipe_end::completion_routine(DWORD error, DWORD transferred, OVERLAPPED* overlapped) {
    	std::unique_ptr<context_type> context(CONTAINING_RECORD(overlapped, context_type, overlapped));
    
    	if (error)
    		throw std::runtime_error("read pipe completion failure");
    
    	std::cout << transferred << std::endl;
    
    	DisconnectNamedPipe(context->pipe);
    	CloseHandle(context->pipe);
    }
    


  • Dass beim Error-Handling das delete zu früh kommt weiß ich, aber das war auch nicht die Ursache.



  • Lies dir einfach mal die MSDN-Beschreibung zu ConnectNamedPipe() durch.
    Ganz unten wird dein Problem beschrieben!


Anmelden zum Antworten