Re: Hung thread in SmbTree.java

Michael B Allen <[email protected]> Thu, 19 Feb 2015 12:33:50 -0500
Newsgroups gmane.network.samba.java
Message-ID <CAGMFw4j9vDRqsSYPvigOe75eYPBszmLgVAFTUeNN3xperyBXLg@mail.gmail.com>
On Wed, Feb 18, 2015 at 2:52 PM, Rich Hammond <[email protected]> wr=
ote:
> I tried to search the archives and I do not see this issue.  If there is
> another place I should search, please let me know.
> I have a thread that has been hung for days at:
>
>    java.lang.Thread.State: WAITING (on object monitor)
>
>     at java.lang.Object.wait(Native Method)
>
>     - waiting on <0x000000074edf9e60> (a jcifs.smb.SmbTransport)
>
>     at java.lang.Object.wait(Object.java:503)
>
>     at jcifs.smb.SmbTree.treeConnect(SmbTree.java:143)
>
>     - locked <0x000000074edf9e60> (a jcifs.smb.SmbTransport)
>
>     at jcifs.smb.SmbFile.doConnect(SmbFile.java:911)
<snip>
>
>
> Looking at the sources for SmbTree I have a couple questions:
>
> In the treeConnect method why does the catch bother to call treeDisconnec=
t?
> The connectionState =3D 1 and treeDisconnect returns immediately in that =
case,
> so why bother calling at all?

Hi Rich,

No. It is possible for connectionState to change after set to 1
because something could call a method that calls wait() on the
transport which would unlock it. And in fact, session.send() calls
transport.send() which ultimately calls wait() on the transport.

> Should not the rule be that anyplace that one sets connectionState =3D 0;=
 you
> also call session.transport.notifyAll()?  Why doesn=E2=80=99t the catch b=
lock have a
> notifyAll()?

Yes. It looks like there is a flaw here. I have added this issue to
the TODO list.

But in this case I might try to just set connectionState =3D 0 in the
treeDisconnect where it returns and thus dodges the notifyAll and then
instead let it fall through to the existing notifyAll():

    void treeDisconnect( boolean inError ) {
synchronized (session.transport()) {

        if (connectionState !=3D 2) { // not-connected
            if (inError) {
                connectionState =3D 0;
            }
        } else {
            ...
        }

        session.transport.notifyAll();
}
    }

So the philosophy is that whenever connectionState changes to
anything, you always call notifyAll. There should not have been a
return in this block.

But this sort of code is non-trivial. I would have to play with it and
test it to make sure it's good so this is not the official fix.

Again, I put this on the TODO list for further investigation.

Thanks a lot for the feedback. Nice catch!

Mike

--
Java Active Directory Integration
http://www.ioplex.com/