SimulPiscator / AirSane

Publish SANE scanners to MacOS, Android, and Windows via Apple AirScan.
GNU General Public License v3.0
251 stars 26 forks source link

segfault on unavailable USB scanner #42

Closed meiser79 closed 3 years ago

meiser79 commented 3 years ago

My server running AirSane is a KVM VM. When I power-on my Brother scanner, the device is attached to the VM via a udev rule. When I power-off the scanner, the device is currently NOT detached from the VM (issue with udev remove rule).

That's why the device is still shown in lsusb output and AirSane thinks that it's still available.

As soon as e.g. AirSane tries to access the scanner because AIC requests a preview scan, AirSane segfaults.

Here's the gdb backtrace (first part is a successful preview scan after powering on the device, the second is the one causing the segfault as device is powered off): gdb-backtrace.txt

SimulPiscator commented 3 years ago

Thank you for the report. In fact, AirSane gets a SANE error when trying to open the switched-off device, and properly ignores it. The segfault happens in Scanner::open() which contains very little code that can segfault at all, so it seems to be the scanner object that has been destroyed or compromised before the call to Scanner::open(). I need to look further into this.

SimulPiscator commented 3 years ago

In the client thread, I was using a reference to a shared_ptr rather than a copy. As a result, scanner objects could be deleted by a device-rescan while still being used in the client thread. The bug is fixed now.

Let me know whether it works better for you now.

meiser79 commented 3 years ago

The segfault is fixed, thanks!

But AirSane hangs now at sane_open() when switching-on the scanner again, I have to restart it so that it works again.

document format used: image/png
using color gamma of 0.555555
sane_init(nullptr, nullptr)
sane_open(brother4:bus1;dev2) -> hotplug event, reloading configuration
received SIGHUP, reloading
reading device options from '/etc/airsane/options.conf'
enumerating local devices...
sane_get_devices() ...
... sane_get_devices() -> SANE_Status Success
found: brother4:bus1;dev2 (Brother DCP-1510)
sane_open(brother4:bus1;dev2) -> SANE_Status Error during device I/O
error: failed to open device
listening on 192.168.1.2:8090
listening on [ipv6-address]:8090
listening on [fe80::5054:ff:fe21:d971]:8090
SANE_Status Invalid argument
sane_exit()
hotplug event, reloading configuration
received SIGHUP, reloading
reading device options from '/etc/airsane/options.conf'
enumerating local devices...
sane_init(nullptr, nullptr)
sane_get_devices() ...
... sane_get_devices() -> SANE_Status Success
sane_exit()
found: brother4:bus1;dev2 (Brother DCP-1510)
sane_init(nullptr, nullptr)
sane_open(brother4:bus1;dev2) -> 
SimulPiscator commented 3 years ago

Thanks for the report. I don't think I can do anything about this, as the code hangs in sane_open(). Do you get similar behavior when unplugging/plugging the USB cable rather than powering off the scanner?

meiser79 commented 3 years ago

Yes, it's exactly the same behaviour when unplugging/plugging the USB cable.

Could you help me understand why you can't do anything if it hangs in sane_open()?

SimulPiscator commented 3 years ago

It is the responsibility of the backend to make sure sane_open() terminates, either successfully or with an error. How should I be able to guess when it is safe to call the function, and when not?