Skip to content

Conversation

@biergaizi
Copy link
Contributor

In drivers/huawei-ups2000.c, the serial port is opened twice. Once by ser_open() to manually perform device identification, once by modbus_connect() for communicating with the UPS after identification succeeds.

However, holding two file descriptors of the same serial port is problematic on Windows, even if they're not actually used at the same time. A serial port is usually opened on Windows via CreateFileA() with dwShareMode = 0, which is done by libmodbus. According to the Win32 API documentation:

If this parameter is zero and CreateFile succeeds, the file or device cannot be shared and cannot be opened again until the handle to the file or device is closed.

This is responsible for the following error on Windows:

modbus_connect: unable to connect: No error
Driver failed to start (exit status=1)

This commit leaves only the raw ser_open() call in upsdrv_initups(), the modbus_connect() call is deleted to avoid opening the same serial port again. After device identification succeeds later in ups2000_device_identification() - called by upsdrv_initinfo(), the raw serial port is closed. Once at this point, modbus_connect() is called, just before upsdrv_initinfo() returns.

networkupstools#3244.

In drivers/huawei-ups2000.c, the serial port is opened twice. Once by
ser_open() to manually perform device identification, once by
modbus_connect() for communicating with the UPS after identification
succeeds.

However, holding two file descriptors of the same serial port is
problematic on Windows, even if they're not actually used at the same
time. A serial port is usually opened on Windows via CreateFileA() with
dwShareMode = 0, which is done by libmodbus. According to the Win32
API documentation:

> If this parameter is zero and CreateFile succeeds, the file or device
> cannot be shared and cannot be opened again until the handle to the
> file or device is closed.

This is responsible for the following error on Windows:

    modbus_connect: unable to connect: No error
    Driver failed to start (exit status=1)

This commit leaves only the raw ser_open() call in upsdrv_initups(),
the modbus_connect() call is deleted to avoid opening the same serial
port again. After device identification succeeds later in
ups2000_device_identification() - called by upsdrv_initinfo(), the raw
serial port is closed. Once at this point, modbus_connect() is called,
just before upsdrv_initinfo() returns.

Signed-off-by: Yifeng Li <[email protected]>
@AppVeyorBot
Copy link

@jimklimov
Copy link
Member

Looks reasonable, thanks for the quick reaction, and happy holidays! :)

(Disregard the Appveyor and OBS faults for that commit, those CI services timed out the free allowance)

@biergaizi
Copy link
Contributor Author

biergaizi commented Jan 6, 2026

CentOS_8/ppc64le failed because the VM failed to power on. AppVeyor failed because it timed out while it was trying to update the build cache.

Build execution time has reached the maximum allowed time for your plan (60 minutes).

Fortunately the build artifact has already been uploaded before it failed.

Both errors are safe to ignore. Let's merge it after #3244 reports back with a positive outcome.

@biergaizi
Copy link
Contributor Author

biergaizi commented Jan 6, 2026

Just tested on my personal machine (the same FreeBSD server originally used for development), no regression found on POSIX. Now waiting for end-user Windows testing...

@biergaizi
Copy link
Contributor Author

biergaizi commented Jan 7, 2026

I think this Pull Request can be merged now, as it's reported that the serial port function is now fixed on Windows. NUT is still not functional due to other problems (awaiting for information), but we can troubleshoot those problems later.

@jimklimov
Copy link
Member

Great, thanks a lot for "knowing where to kick"! ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants