2011-10-05 382 views
7

CreateFile()を使用してシリアルポートを開きます。私は一貫してCreateFile()INVALID_HANDLE_VALUEGetLastError()を返してERROR_SUCCESSを返すテストケースを持っています(再配分するには複雑すぎる)。このバグは、あるスレッドが他のポートがポートを閉じるのと全く同じタイミングでポートを開く場合にのみ発生します。ポートを開くスレッドがこの問題を迂回します。CreateFile()はINVALID_HANDLE_VALUEを返しますが、GetLastError()はERROR_SUCCESSです

私はこの違いがあるのか​​どうかはわかりませんが、コードでは後でCreateIoCompletionPortを使ってポートをCompletionPortに関連付けます。私はこの種のものは発生しないはずですかなり確信している

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; 
} 

は、ここに私のコードです。私は間違って何かしていますか?正しい結果が返されるようにAPIを取得するにはどうすればよいですか?


詳細

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); 
} 

:ここ

JPeripheralは、実際の(unsanitized)のソース・コードです。このコードは、私が開発したシリアル・ポート・ライブラリーから取られます実際の出力は次のとおりです。

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. 
+0

これらの行は、テストで使用している正確な行ですか?どんな簡素化(明らかに無害なものでさえも)は、問題の原因を隠すことができます。 –

+0

アクセスしているハードウェアは? – Gabe

+0

@Gabe:社内で開発した組み込みデバイスにアクセスしています。それは私のPCに接続した標準のDB9シリアルポート接続を持っています(USB-RS232アダプターはここにありません)。 – Gili

答えて

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

cerrへの出力により、winapiがフードの下で呼び出されます。 GetLastError()によって返されたスレッドエラー値がリセットされます。修正:

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

私は確信していません。この問題を抱えていた元のコードには、 'cer'命令が含まれていませんでした。私は最近それを追加しました。あなたは上記のコードに何か間違っていると思いますか( 'cerr'を除く)? – Gili

+1

あなたが示した出力トレースは、* GetLastError値を壊してしまうコードでしか生成できません。私はそれが失敗することを疑うことはありません、失敗するCOMポートを開くための多くの理由があります。 –

+0

あなたは正しいです。失敗したポイントと 'GetLastError()の読み込みの間にどれくらいのコードが存在するのかを確認してください(エラーコード:jace :: java_new (L" CreateFile()はエラーで失敗しました: "+ getErrorMessage(GetLastError()))ありがとう! – Gili

関連する問題