Socket closed while setting SaneOption value
Closed this issue · 13 comments
Hi everyone, sorry to bother.
While setting option values (any type) I get a socket closed exception in SaneOption.writeWordListOption(List value)
java.net.SocketException: Socket closed at java.net.SocketOutputStream.socketWrite(SocketOutputStream.java:118) at java.net.SocketOutputStream.write(SocketOutputStream.java:155) at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82) at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140) at au.com.southsky.jfreesane.SaneOption.writeWordListOption(SaneOption.java:624) at au.com.southsky.jfreesane.SaneOption.writeOption(SaneOption.java:657) at au.com.southsky.jfreesane.SaneOption.setFixedValue(SaneOption.java:492)
SaneOutputStream out = device.getSession().getOutputStream();
returns an open stream however later on the flush fails.
Any idea that can help me?
thanks in advance
private ControlOptionResult writeWordListOption(List value) throws IOException, SaneException { Preconditions.checkState(isWriteable(), "option is not writeable"); Preconditions.checkState(isActive(), "option is not active"); SaneOutputStream out = device.getSession().getOutputStream(); out.write(SaneRpcCode.SANE_NET_CONTROL_OPTION); out.write(device.getHandle().getHandle()); out.write(SaneWord.forInt(optionNumber)); out.write(SaneWord.forInt(OptionAction.SET_VALUE.getWireValue())); out.write(getValueType()); out.write(SaneWord.forInt(value.size() * SaneWord.SIZE_IN_BYTES)); // Write the pointer to the words out.write(SaneWord.forInt(value.size())); for (SaneWord element : value) { // and the words themselves out.write(element); } out.flush(); ControlOptionResult result = handleWriteResponse(); if (result.getInfo().contains(OptionWriteInfo.RELOAD_OPTIONS) || result.getInfo().contains(OptionWriteInfo.RELOAD_PARAMETERS)) { device.invalidateOptions(); device.listOptions(); } return result; }
Are you able to share the code that is calling into jfreesane?
hmm, what bit would be relevant?
The part that calls "setFixedValue", for example.
I suspect your SANE daemon is somehow misconfigured and is closing the socket shortly after it's opened. You could confirm with server logs.
Ok, strangely enough if I catch those exceptions and continue I am able to get images back (I am using the test configuration).
In fact if at this point
SaneOutputStream out = device.getSession().getOutputStream();
I inspect device.isOpen(), that returns true
Can you share the code you're using to call into JFreeSane? Where are you catching exceptions? Which socket is closed? If the socket to the SANE server is closed, there's no way you should be able to retrieve images.
Help me understand how you're using SANE/jfreesane.
Well, there is not much to show. I am going by the manual
SaneDevice device = ...;
device.open();
List options = device.listOptions();
then I set a value to a given option (using the setter according to the type) (this step fails with socket closed exception)
then I do device.acquireImage()
And I get a color test image as set in the configuration file.
I am using Ubuntu16.04 64 on VMWareFusion, and a saned daemon with a virtual device configured.
Tomorrow I'll put my hands on a physical device and I'll see. Up to now I don't understand. I'll get back to you, thanks
Oh, let me see if I can find that one. thanks
Ok. I am working with a Kodak ScanMate i940 now. I see the same problem this time while acquiring images.
My client code:
@Override public BufferedImage doScan() throws xxxSaneException { if (!device.isOpen()) openDevice(); Logger logger = getLogger(); try { logger.info(Messages.getString("akey", getName())); //$NON-NLS-1$ return device.acquireImage(); } catch (Exception e) { Device.getExecutor().submit(()-> Try.run(()->((SaneDevice)device).close())); logger.log(Level.SEVERE, "doScan() " + e.getClass().getName() + ": "+ e.getMessage()); throw new xxxJSaneException(e); } finally { logger.info(Messages.getString("anotherKey", getName())); //$NON-NLS-1$ } }
So here, preconditions are met
public BufferedImage acquireImage(ScanListener listener) throws IOException, SaneException { Preconditions.checkState(isOpen(), "device is not open"); if (listener == null) { listener = new ScanListenerAdapter(); } return session.acquireImage(this, listener); }
error is thrown in line marked as bold, with a socketClosedException
BufferedImage acquireImage(SaneDevice device, ScanListener listener) throws IOException, SaneException { SaneImage.Builder builder = new SaneImage.Builder(); SaneParameters parameters = null; listener.scanningStarted(device); int currentFrame = 0; do { SaneDeviceHandle handle = device.getHandle(); outputStream.write(SaneRpcCode.SANE_NET_START); outputStream.write(handle.getHandle()); outputStream.flush(); SaneWord startStatus = inputStream.readWord(); int port = inputStream.readWord().integerValue(); SaneWord byteOrder = inputStream.readWord(); String resource = inputStream.readString(); ...
Server log reads
07:15:04 osboxes systemd[1]: Started Scanner Service (127.0.0.1:55110). Jan 9 07:15:04 osboxes saned[35837]: saned (AF-indep+IPv6+systemd) from sane-backends 1.0.25git starting up Jan 9 07:15:04 osboxes saned[35837]: check_host: access by remote host: ::ffff:127.0.0.1 Jan 9 07:15:04 osboxes saned[35837]: init: access granted to osboxes@::ffff:127.0.0.1 Jan 9 07:15:15 osboxes gnome-session[2384]: Memory pressure relief: Total: res = 7553024/7561216/8192, res+swap = 5726208/5730304/4096 Jan 9 07:15:28 osboxes saned[35837]: saned exiting
thanks!
It certainly doesn't look like saned is closing the socket. The only reason that should happen on the client side is because of a call to SaneSession.close
.
Do you keep the SaneSession around for the duration of your scanning?
Oh! I am very sorry you are right.
disclaimer: I am migrating an existing code to use jfreesane (a code that I am not very familiar with)
thanks a lot for your time
No problem, glad we got it sorted.