Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How set limited time when calling CreateFile to open a serial port "comX"?

I have a bluetooth serial port to communicate with hardwares. If the hardware does not power on, using "CreateFile" will make thread blocked and cause a error "The semaphore timeout period has expired" after 5-6 seconds. Is it possible to spend less time getting the result of using "CreateFile" by setting timeout-time ? Thank you.

like image 550
Mix Avatar asked Dec 04 '25 15:12

Mix


1 Answers

unfortunately CreateFile is synchronous only api which not take any timeout parameter (even low level ZwCreateFile not have this functional).

maximum what you can do in this case - move call CreateFile to separate thread, and if after some time it not finished - call CancelSynchronousIo for this thread. this can help but only can - I/O Completion/Cancellation Guidelines

All IRPs (including Create) that can take an indefinite amount of time must be able to be cancelled

but I/O Subsystem Depends on Drivers - so result will be depended - are driver which handle serial port implement cancelation of IRP_MJ_CREATE

struct OPEN_PACKET 
{
    PCWSTR lpFileName;
    HANDLE hFile;
    DWORD error;
    DWORD dwDesiredAccess;
    DWORD dwShareMode;
    DWORD dwCreationDisposition;
    DWORD dwFlagsAndAttributes;
};

DWORD WINAPI OpenComPort(OPEN_PACKET* op)
{
    HANDLE hFile = CreateFile(op->lpFileName, op->dwDesiredAccess, op->dwShareMode, 
        NULL, op->dwCreationDisposition,op->dwFlagsAndAttributes, NULL);

    op->error = hFile == INVALID_HANDLE_VALUE ? GetLastError() : NOERROR;
    op->hFile = hFile;

    return GetLastError();// for possible use GetExitCodeThread but use op->error better
}

void testCC(PCWSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes)
{
    OPEN_PACKET op = { lpFileName, INVALID_HANDLE_VALUE, ERROR_IO_PENDING, 
        dwDesiredAccess, dwShareMode, dwCreationDisposition, dwFlagsAndAttributes };

    ULONG ticks = GetTickCount();

    if (HANDLE hThread = CreateThread(NULL, PAGE_SIZE, (PTHREAD_START_ROUTINE)OpenComPort, &op, 0, NULL))
    {
        if (WaitForSingleObject(hThread, 1000) == WAIT_TIMEOUT)//1 sec for example
        {
            CancelSynchronousIo(hThread);
            WaitForSingleObject(hThread, INFINITE);
        }
        CloseHandle(hThread);
    }
    else
    {
        op.error = GetLastError();
    }

    ticks = GetTickCount() - ticks;

    WCHAR sz[256];
    if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, op.error, 0, sz, RTL_NUMBER_OF(sz), NULL)) *sz = 0;
    DbgPrint("[%u ms] hFile=%p err=%u %S\n", ticks, op.hFile, op.error, sz);

    if (op.hFile != INVALID_HANDLE_VALUE)
    {
        CloseHandle(op.hFile);
    }
}

void ep()
{
    testCC(L"\\\\server\\share\\1.txt", FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_SHARE_VALID_FLAGS, OPEN_EXISTING, 0);
    testCC(L"\\\\?\\globalroot\\systemroot\\notepad.exe", FILE_GENERIC_READ|FILE_GENERIC_WRITE, FILE_SHARE_VALID_FLAGS, OPEN_EXISTING, 0);
    testCC(L"\\\\?\\globalroot\\systemroot\\notepad.exe", FILE_GENERIC_READ, FILE_SHARE_VALID_FLAGS, OPEN_EXISTING, 0);
}

and I get the next results:

[1000 ms] hFile=FFFFFFFFFFFFFFFF err=995 The I/O operation has been aborted because of either a thread exit or an application request.

[0 ms] hFile=FFFFFFFFFFFFFFFF err=5 Access is denied.

[0 ms] hFile=0000000000000154 err=0 The operation completed successfully.
like image 63
RbMm Avatar answered Dec 07 '25 03:12

RbMm



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!