Discussion:
[jcifs] Disconnect from a share
Mathias Dietz
2005-08-11 14:05:15 UTC
Permalink
there is no way to make a clean disconnect from a share after doing some
stuff .

E.g.
System.out.println("CONNECT TO: smb://" + ip + "/smb_control/");
SmbFile smb =new SmbFile("smb://;:@" + ip+ "/smb_control/");
String[] sm = smb.list();
System.out.println("Finished !");
//here close the SMBSession , Transport

The only way to disconnect, seems to be the socket timeout (
jcifs.smb.client.soTimeout) but
this generates ugly error messages on the server :
Aug 11 15:30:17 back1 smbd[30618]: write_socket: Error writing 43 bytes
to socket 26: ERRNO = Broken pipe

I would prefer a disconnect() method in SmbFile which does something like:
/**
* Disconnect from server.
* WARNING! Closes the SMBTransport and all active SMBSession's.
* Should only be called if no other SMBSession is alive or required.
* @param boolean hard , If false close only if no active request is
outstanding.
*/
public void disconnect(boolean hard){
tree.session.transport.disconnect(hard);
}

or a transport_idle_timeout , which makes a clean disconnect before closing
the socket.

@Michael: Would you kindly implement such a function , or do you accept a
patch ?



mit freundlichen Grüßen / best regards

Mathias Dietz

------------------------------------------------------------------------
Software Development Dept. A182
IBM Deutschland GmbH
Hechtsheimer Strasse 2 Geb.83
D-55131 Mainz
Phone (+49)-6131-84-2027
Fax (+49)-6131-84-3111
E-Mail : ***@de.ibm.com
IBM Certified Professional Server Specialist
------------------------------------------------------------------------
Visit Open Enterprise System Virtualization:
IBM intranet ---> http://w3.ais.mainz.de.ibm.com/stonehenge/
Internet ---> http://www-5.ibm.com/services/de/its/filestore.html
Michael B Allen
2005-08-11 18:32:27 UTC
Permalink
On Thu, 11 Aug 2005 16:05:15 +0200
Post by Mathias Dietz
there is no way to make a clean disconnect from a share after doing some
stuff .
Transports timeout and close after being idle for 15000 milliseconds.
Post by Mathias Dietz
E.g.
System.out.println("CONNECT TO: smb://" + ip + "/smb_control/");
String[] sm = smb.list();
System.out.println("Finished !");
//here close the SMBSession , Transport
The only way to disconnect, seems to be the socket timeout (
jcifs.smb.client.soTimeout) but
Aug 11 15:30:17 back1 smbd[30618]: write_socket: Error writing 43 bytes
to socket 26: ERRNO = Broken pipe
This error should not occur with a reasonable soTimeout value. I think
you might be setting soTimeout too low.
Post by Mathias Dietz
/**
* Disconnect from server.
* WARNING! Closes the SMBTransport and all active SMBSession's.
* Should only be called if no other SMBSession is alive or required.
outstanding.
*/
public void disconnect(boolean hard){
tree.session.transport.disconnect(hard);
}
or a transport_idle_timeout , which makes a clean disconnect before closing
the socket.
That's what soTimeout does. When the transport is idle for longer than
jcifs.smb.client.soTimeout jCIFS will transmit the appropriate loggoff
and disconnect messages and then close the underlying socket. This should
not generate an error on the server or the client.

Note that soTimeout is in *milliseconds*. The default is 15000 meaning
15 seconds. If you specify something like 3, thinking it's 3 seconds,
the transport will close before the request is sent or after it's sent
but before the response is received. In both cases this is not what you
want and will likely generate an error somewhere.
Post by Mathias Dietz
@Michael: Would you kindly implement such a function , or do you accept a
patch ?
If you can provide a compelling *reason* then yes. Otherwise, no.

In future versions this behavior will be changed slightly. In particular
refcounting will be used to block transports from closing so that
handles that are left open without activity remain valid. Currently if
you open a file and wait it will be closed when soTimeout expires and
then transparently reopened as necessary. This works but technically it
is bad and future functionality cannot be properly supported with the
current behavior (e.g. file locks).

Thanks,
Mike
Ronny Schuetz
2005-08-12 12:55:47 UTC
Permalink
Post by Michael B Allen
That's what soTimeout does. When the transport is idle for longer than
jcifs.smb.client.soTimeout jCIFS will transmit the appropriate loggoff
and disconnect messages and then close the underlying socket. This should
not generate an error on the server or the client.
Post by Mathias Dietz
@Michael: Would you kindly implement such a function , or do you accept a
patch ?
If you can provide a compelling *reason* then yes. Otherwise, no.
I'm planning to use jCIFS for a system that connects to several servers
(>100) and transports files from one to another. Due to the global
nature of the timeout settings, the timeout needs to be set to a high
value, as the system is a) connecting servers distributed worldwide
which are b) not responding as quickly as expected always. A prototype
required timeout settings of 2min or more.

So in such a scenario, it would be really nice, to be able to disconnect
and close unnecessary connections immediately, instead of waiting until
they time out wasting resources.

Thx,
Ronny
Michael B Allen
2005-08-12 19:25:06 UTC
Permalink
On Fri, 12 Aug 2005 14:55:47 +0200
Post by Ronny Schuetz
Post by Michael B Allen
That's what soTimeout does. When the transport is idle for longer than
jcifs.smb.client.soTimeout jCIFS will transmit the appropriate loggoff
and disconnect messages and then close the underlying socket. This should
not generate an error on the server or the client.
Post by Mathias Dietz
@Michael: Would you kindly implement such a function , or do you accept a
patch ?
If you can provide a compelling *reason* then yes. Otherwise, no.
I'm planning to use jCIFS for a system that connects to several servers
(>100) and transports files from one to another. Due to the global
nature of the timeout settings, the timeout needs to be set to a high
value, as the system is a) connecting servers distributed worldwide
which are b) not responding as quickly as expected always. A prototype
required timeout settings of 2min or more.
So in such a scenario, it would be really nice, to be able to disconnect
and close unnecessary connections immediately, instead of waiting until
they time out wasting resources.
Adding a disconnect() method isn't the proper solution to this problem.
I think the refcounting technique I described eariler would be more
appropriate. For now you can easily extend SmbFile to modify the behavior
in a variety of ways.

Mike
Mathias Dietz
2005-08-12 12:23:41 UTC
Permalink
Post by Michael B Allen
This error should not occur with a reasonable soTimeout value. I think
you might be setting soTimeout too low.
I've used the default value , but error occurs also with
jcifs.Config.setProperty("jcifs.smb.client.soTimeout", "15000");
Post by Michael B Allen
That's what soTimeout does. When the transport is idle for longer than
jcifs.smb.client.soTimeout jCIFS will transmit the appropriate loggoff
and disconnect messages and then close the underlying socket. This should
not generate an error on the server or the client.
Yes, you are right.I had overlooked it.But the error in the server log
(samba 3.0.14a)
still occurs.

After some debugging (comparing tcp packages from smbclient with jcifs), I
found two causes for the "Broken Pipe" error.

1) doDisconnect() sends a LogoffAndX packet and doesn't wait for the
response.
This causes a server error message (Error writing xx bytes to client).
Solution: In SMBSession.logoff(boolean) replace
transport.send( request, null );
with
transport.send( request, new SmbComLogoffAndX(null));

2) The Java VM sends a TCP RST package when you close the socket, smbclient
sends a TCP FIN package.
I found a description of the problem here:
http://java.sun.com/security/javaone/2003/2240-Networking.pdf
Solution: In SMBTransport.doDisconnect(..) add:
socket.shutdownOutput();
above of ->
out.close();
in.close();

I'm still very interessted in a disconnect() method , because I use jcifs
to monitor multiple samba servers (up to 100).
And I must create a new connection each 10-15 seconds.A disconnect() method
would help to save a lot of
resources (# of threads) und would make life easier.


best regards

Mathias Dietz

------------------------------------------------------------------------
Software Development Dept. A182
IBM Deutschland GmbH
Hechtsheimer Strasse 2 Geb.83
D-55131 Mainz
Phone (+49)-6131-84-2027
Fax (+49)-6131-84-3111
E-Mail : ***@de.ibm.com
IBM Certified Professional Server Specialist
------------------------------------------------------------------------
Visit Open Enterprise System Virtualization:
IBM intranet ---> http://w3.ais.mainz.de.ibm.com/stonehenge/
Michael B Allen
2005-08-12 20:21:22 UTC
Permalink
On Fri, 12 Aug 2005 14:23:41 +0200
Post by Mathias Dietz
After some debugging (comparing tcp packages from smbclient with jcifs), I
found two causes for the "Broken Pipe" error.
1) doDisconnect() sends a LogoffAndX packet and doesn't wait for the
response.
This causes a server error message (Error writing xx bytes to client).
Solution: In SMBSession.logoff(boolean) replace
transport.send( request, null );
with
transport.send( request, new SmbComLogoffAndX(null));
Ok, I think I see what's happening. But first, note that second
parameter to SmbTransport.send() is actually a response object so
passing an SmbComLogoffAndX is invalid. You got lucky because the
SmbComLogoffAndXResponse decodes no data. A more appropriate object
would be SmbComBlankResponse.

But passing null to the transport indicates that it should not to wait
for the response. This is slightly faster since we can move on to other
things rather than sit there collecting a logging off response which
has no useful information in it.

The problem is that first of "other things" is to close the socket but
apparently Samba hasn't written it's response yet so when it tries to
do so it get's an error (albeit a harmless one).
Post by Mathias Dietz
2) The Java VM sends a TCP RST package when you close the socket, smbclient
sends a TCP FIN package.
http://java.sun.com/security/javaone/2003/2240-Networking.pdf
socket.shutdownOutput();
above of ->
out.close();
in.close();
Interesting! I never noticed this. I would prefer to send a FIN. I'll
add this to The List.

If you do 2 and not 1 does it fix the error? I would rather NOT wait
for the logoff response.
Post by Mathias Dietz
I'm still very interessted in a disconnect() method , because I use jcifs
to monitor multiple samba servers (up to 100).
And I must create a new connection each 10-15 seconds.A disconnect() method
would help to save a lot of
resources (# of threads) und would make life easier.
Again, the proper solution here is to add refcounting to the
transport. That way you can leave soTimeout at 15 seconds (actually in
your case you would probably want to make it 5 seconds) but when a request
is outstanding on the transport it cannot be closed. That change is too
invasive for me to add to mainline while we're in a stable period so
you might elect to simply extend SmbFile to add your disconnect() method.

Note that depending on what your doing a change in algorithm might
dramatically improve performance. Double check that the problem really
is that your not getting a response from the server for 2+ minutes. It
could be something else. For example, the naive way to write a crawler
is to do post order DFS. The problem with that is that you end up with
a huge list of nodes that have an expired attExperiationPeriod and/or
the transport has timed out. That means that when that node is examined
again jcifs needs to query the attributes again and/or create the
transport. That is horribly slow. The solution is to keep the crawing
list very short. Meaning do listFiles() and then query those nodes
immediately. Meaning used breadth first search. When combined with a
thread pool performance can be quite good.

Mike
Michael B Allen
2005-08-19 21:01:47 UTC
Permalink
On Fri, 12 Aug 2005 16:21:22 -0400
Post by Michael B Allen
Post by Mathias Dietz
2) The Java VM sends a TCP RST package when you close the socket, smbclient
sends a TCP FIN package.
http://java.sun.com/security/javaone/2003/2240-Networking.pdf
socket.shutdownOutput();
above of ->
out.close();
in.close();
Interesting! I never noticed this. I would prefer to send a FIN. I'll
add this to The List.
I've added this shutdownOutput although I can't see that it's made a
difference because I couldn't reproduce the RSTs in the first place. I'd
be curious to know if 1.2.2 makes a difference for you.

Mike

Continue reading on narkive:
Loading...