Re: NullPointerException in Dfs.resolve

Martin Kutter <[email protected]> Mon, 15 Jun 2015 13:45:22 +0200
Newsgroups gmane.network.samba.java
Message-ID <[email protected]>
Thanks for your reply.
I've tested 1.3.18b - it does not fix this specific error.

Regarding the fix suggested by Conrad: In the meantime, I've also=20
implemented a fix for the issue - I changed SmbFile.resolveDfs()=20
(lines 671 and following) to

DfsReferral dr =3D null;
// disconnect is synchronized to transport, too.
// make sure our transport doesn't get disconnected while
// we're inside the synchronized block
synchronized (tree.session.transport) {
    if (tree.session.transport.tconHostName =3D=3D null) {
        // disconnect properly if connection is lost
        tree.treeDisconnect(false);
    }
    tree.session.transport.connect();
    dr =3D dfs.resolve(tree.session.transport.tconHostName,=20
        tree.share,=20
        unc,=20
        auth);
}
if (dr !=3D null) {


As my knowledge of CIFS is quite limited, I have no idea whether this
is right (or has bad side effects).

The idea behind is similar (but not equal) to Conrad's fix: In case the=20
transport has disconnected, disconnect properly and reconnect.

Best regards,

Martin

On Sun, 14 Jun 2015 11:37:48 -0400, Michael B Allen <[email protected]>
wrote:
> I have added this post to the list of people who have reported it to
> the TODO list so that it can be considered when I get around to
> looking at this.
>=20
> Note that the 1.3.18b mentioned in the link cited is here:
>=20
>    http://jcifs.samba.org/old/jcifs-1.3.18b.jar
>=20
> Although I cannot recall what it actually does anymore it might be
> worth a try. We never received feedback about it.
>=20
> Mike
>=20
> On Sun, Jun 14, 2015 at 5:00 AM, Conrad Herrmann <[email protected]>
> wrote:
>> Martin,
>>
>>
>>
>> I have recently run into the same problem.
>>
>>
>>
>> I think the problem is that SmbFile.resolveDfs() uses the currently
>> connected transport as the DFS resolver/domain server
>> (tree.session.transport.tconHostName), but it is very possible that
>> there is
>> no currently connected transport.  In your case, that happens when the
>> file
>> server forces the TCP connection to close, and the transport tears
itself
>> down.
>>
>>
>>
>> And, although the resolveDfs() method calls connect0(), in fact this
does
>> nothing because doConnect() doesn't force creation of a new connection
>> if we
>> are talking about a DFS resolved path.
>>
>>
>>
>> It seems to me that in that case, we have to start over again at the
top
>> of
>> the referral tree, with the Domain.
>>
>>
>>
>> So my solution has this:  change the code for SmbFile.resolveDfs()
lines
>> 671
>> (or so) so that it says:
>>
>>
>>
>>         connect0();
>>
>>
>>
>>>        String hostName =3D tree.session.transport.tconHostName;
>>
>>>        String domainDfsServerName =3D getServerWithDfs();
>>
>>>        if (hostName =3D=3D null)
>>
>>>            hostName =3D domainDfsServerName;
>>
>>
>>
>>         DfsReferral dr =3D dfs.resolve(
>>
>>>                    hostName,
>>
>>                     tree.share,
>>
>>                     unc,
>>
>>                     auth);
>>
>>
>>
>> The code comes from the other use of tconHostName, in
>> SmbFile.doConnect():
>>
>>         String hostName =3D getServerWithDfs();
>>
>>         tree.inDomainDfs =3D dfs.resolve(hostName, tree.share, null,
auth)
>>         !=3D
>> null;
>>
>> In this code, we are getting the DFS resolver (which might be the
domain
>> server) as the hostName, and asking it to resolve our share.
>>
>>
>>
>> Basically what this new code is saying is that:
>>
>> - in the case where the transport has closed (ie, because of a timeout
or
>> TCP close on the DFS server side) reconnect to the DFS domain server i=
n
>> order to resolve a share's DFS server.
>>
>>
>>
>> I can imagine a case where this doesn't work--if we have multiple
levels
>> of
>> DFS redirection, where the domain server cannot redirect the client to
a
>> deep subdirectory.  But, I don't even know if this is possible in DFS.=
=20
>> If
>> it is, then at least this solution removes the top level case and
>> identifies
>> the problem, which would require walking down the DFS resolution path
to
>> resolve the actual file server.
>>
>>
>>
>> Conrad Herrmann
>>
>> Primdaesk, Inc.
>>
>>
>>
>>> Hi,
>>
>>>
>>
>>> I encountered a NullpointerException similar to
>>
>>> https://lists.samba.org/archive/jcifs/2012-January/009856.html - at
>>
>>> least the stack traces are similar.
>>
>>>
>>
>>> My Environment (Client side):
>>
>>> - jcifs 1.3.18
>>
>>> - IBM JDK 7
>>
>>> - AIX 7.1
>>
>>>
>>
>>> The NPE occured in a (in-house) plugin for the Jenkins build server.
In
>>
>>> this system, JCIFs is used to recursively copy files from a Windows
>>
>>> share to an AIX machine.
>>
>>>
>>
>>> Re-running a build shortly after it finished triggered the NPE.
>>
>>>
>>
>>> After some debugging, it seems to me like the SmbFile=E2=80=99s under=
lying
>>
>>> transport is closed (by timeout), and when SmbFile.resolveDfs is
called,
>>
>>> the transport is not reconnected (unlike, for example, later in
>>
>>> SmbFile.resolve, or in SmbSession.getChallenge).
>>
>>>
>>
>>> I was able to reproduce the NPE during debugging using the following
>>
>>> steps:
>>
>>> - Trigger a build (recursively copying from a CIFS DFS tree)
>>
>>> - Wait until the transport objects disconnect by timeout (tracked by
>>
>>> breakpoint)
>>
>>> - Retrigger the build (recursively copying the same directory
structure)
>>
>>>
>>
>>> The Jenkins plugin usually runs the second JCIFS copy operation in th=
e
>>
>>> same thread than the first (though that's not guaranteed).
>>
>>> Each run uses a new SmbFile object.
>>
>>>
>>
>>> Am I missing something (like some close operation on SmbFile)?
>>
>>> Is this a known error?
>>
>>> Can I do something to fix it?
>>
>>>
>>
>>> Best regards,
>>
>>>
>>
>>> Martin
>>
>>>