winapi serial-port createfile iocp getlasterror

winapi - CreateFile() devuelve INVALID_HANDLE_VALUE pero GetLastError() es ERROR_SUCCESS



serial-port iocp (1)

Estoy abriendo un puerto serie usando CreateFile () . Tengo un caso de prueba (demasiado complicado para redistribuir) que causa constantemente que CreateFile() devuelva INVALID_HANDLE_VALUE y GetLastError() para devolver ERROR_SUCCESS . Por lo que parece, este error solo ocurre si un hilo abre el puerto al mismo tiempo que otro puerto lo cierra. El hilo que abre el puerto corre a través de este problema.

No sé si esto hace la diferencia, pero más adelante en el código asocio el puerto con un CompletionPort utilizando CreateIoCompletionPort .

Aquí está mi código:

HANDLE port = CreateFile(L"////.//COM1", GENERIC_READ | GENERIC_WRITE, 0, // must be opened with exclusive-access 0, // default security attributes OPEN_EXISTING, // must use OPEN_EXISTING FILE_FLAG_OVERLAPPED, // overlapped I/O 0); // hTemplate must be NULL for comm devices if (port == INVALID_HANDLE_VALUE) { DWORD errorCode = GetLastError(); cerr << L"CreateFile() failed with error: " << errorCode << endl; }

Estoy bastante seguro de que este tipo de cosas no deberían suceder. ¿Estoy haciendo algo mal? ¿Cómo obtengo la API para devolver un resultado correcto?

MÁS DETALLES : Este código está tomado de una biblioteca de puertos serie que he desarrollado: JPeripheral

Aquí está el código fuente real (no optimizado):

JLong SerialChannel::nativeOpen(String name) { cerr << "nativeOpen(" << name << ")" << endl; wstring nameWstring = name; HANDLE port = CreateFile((L"////.//" + nameWstring).c_str(), GENERIC_READ | GENERIC_WRITE, 0, // must be opened with exclusive-access 0, // default security attributes OPEN_EXISTING, // must use OPEN_EXISTING FILE_FLAG_OVERLAPPED, // overlapped I/O 0); // hTemplate must be NULL for comm devices cerr << "nativeOpen.afterCreateFile(" << name << ")" << endl; cerr << "port: " << port << ", errorCode: " << GetLastError() << endl; if (port == INVALID_HANDLE_VALUE) { DWORD errorCode = GetLastError(); switch (errorCode) { case ERROR_FILE_NOT_FOUND: throw PeripheralNotFoundException(jace::java_new<PeripheralNotFoundException>(name, Throwable())); case ERROR_ACCESS_DENIED: case ERROR_SHARING_VIOLATION: throw PeripheralInUseException(jace::java_new<PeripheralInUseException>(name, Throwable())); default: { throw IOException(jace::java_new<IOException>(L"CreateFile() failed with error: " + getErrorMessage(GetLastError()))); } } } // Associate the file handle with the existing completion port HANDLE completionPort = CreateIoCompletionPort(port, ::jperipheral::worker->completionPort, Task::COMPLETION, 0); if (completionPort==0) { throw AssertionError(jace::java_new<AssertionError>(L"CreateIoCompletionPort() failed with error: " + getErrorMessage(GetLastError()))); } cerr << "nativeOpen.afterCompletionPort(" << name << ")" << endl; // Bind the native serial port to Java serial port SerialPortContext* result = new SerialPortContext(port); cerr << "nativeOpen.afterContext(" << name << ")" << endl; return reinterpret_cast<intptr_t>(result); }

Aquí está el resultado real que obtengo:

nativeOpen(COM1) nativeOpen.afterCreateFile(COM1) port: 00000374, errorCode: 0 nativeOpen.afterCompletionPort(COM1) nativeOpen.afterContext(COM1) [...] nativeOpen(COM1) nativeOpen.afterCreateFile(COM1) port: FFFFFFFF, errorCode: 0 java.io.IOException: CreateFile() failed with error: The operation completed successfully.


HANDLE port = CreateFile(...); cerr << "nativeOpen.afterCreateFile(" << name << ")" << endl; cerr << "port: " << port << ", errorCode: " << GetLastError() << endl; if (port == INVALID_HANDLE_VALUE) { DWORD errorCode = GetLastError();

La salida a cerr invoca llamadas winapi bajo el capó. Lo cual restablecerá el valor de error de subproceso devuelto por GetLastError (). Fijar:

HANDLE port = CreateFile(...); int err = GetLastError(); // etc, use err instead...