[jcifs] bugs in JCIFS 1.2.9

Michael B Allen mba2000 at ioplex.com
Fri Nov 24 16:24:28 GMT 2006


The following thread should cause the writer thread to exit.

   2139         try {
   2140             copyTo0( dest, b, bsize, w, req, resp );
   2141         } finally {
   2142             w.write( null, -1, null, 0 );
   2143         }

I cannot reproduce this problem. I think you are confusing the writer
thread with the Transport threads. You will need to get a thread dump
to verify this.

Run the attached example like:

$ java -Djcifs.properties=../miallen.prp CopyToTest smb://ts0.win.net/tmp/bogus.txt smb://nano.foo.net/pub/bogus.txt
jcifs.smb.SmbException: The system cannot find the file specified.
        at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:511)
        at jcifs.smb.SmbTransport.send(SmbTransport.java:588)
        at jcifs.smb.SmbSession.send(SmbSession.java:239)
        at jcifs.smb.SmbTree.send(SmbTree.java:109)
        at jcifs.smb.SmbFile.send(SmbFile.java:690)
        at jcifs.smb.SmbFile.queryPath(SmbFile.java:1202)
        at jcifs.smb.SmbFile.copyTo0(SmbFile.java:1950)
        at jcifs.smb.SmbFile.copyTo(SmbFile.java:2140)
        at CopyToTest.run(CopyToTest.java:17)

<get a thread dump [1]>

Full thread dump Java HotSpot(TM) Client VM (1.4.2_08-b03 mixed mode):

"Transport2" daemon prio=1 tid=0x093bbae8 nid=0x3eea runnable [4be3000..4be4228]
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.read(SocketInputStream.java:129)
        at jcifs.util.transport.Transport.readn(Transport.java:29)
        at jcifs.smb.SmbTransport.peekKey(SmbTransport.java:352)
        at jcifs.util.transport.Transport.loop(Transport.java:100)
        at jcifs.util.transport.Transport.run(Transport.java:261)
        at java.lang.Thread.run(Thread.java:534)

"Transport1" daemon prio=1 tid=0x093b77d0 nid=0x3eea runnable [2ef6000..2ef7228]
        at java.net.SocketInputStream.socketRead0(Native Method)
        at java.net.SocketInputStream.read(SocketInputStream.java:129)
        at jcifs.util.transport.Transport.readn(Transport.java:29)
        at jcifs.smb.SmbTransport.peekKey(SmbTransport.java:352)
        at jcifs.util.transport.Transport.loop(Transport.java:100)
        at jcifs.util.transport.Transport.run(Transport.java:261)
        at java.lang.Thread.run(Thread.java:534)

"Signal Dispatcher" daemon prio=1 tid=0x0925d8d8 nid=0x3eea waiting on condition [0..0]

"Finalizer" daemon prio=1 tid=0x09248e38 nid=0x3eea in Object.wait() [5a6000..5a6228]
        at java.lang.Object.wait(Native Method)
        - waiting on <0xae3573f0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:111)
        - locked <0xae3573f0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:127)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=1 tid=0x09248290 nid=0x3eea in Object.wait() [4eb000..4eb228]
        at java.lang.Object.wait(Native Method)
        - waiting on <0xae357290> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:429)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:115)
        - locked <0xae357290> (a java.lang.ref.Reference$Lock)

"main" prio=1 tid=0x092129a0 nid=0x3eea waiting on condition [bff37000..bff3729c]
        at java.lang.Thread.sleep(Native Method)
        at CopyToTest.main(CopyToTest.java:27)

"VM Thread" prio=1 tid=0x09247030 nid=0x3eea runnable 

"VM Periodic Task Thread" prio=1 tid=0x092600d8 nid=0x3eea waiting on condition 
"Suspend Checker Thread" prio=1 tid=0x0925cf20 nid=0x3eea runnable 

You can see above there is no "JCIFS-WriterThread" listed.

Now wait 20 seconds for the Transport threads to exit and do a thread
dump again:

Full thread dump Java HotSpot(TM) Client VM (1.4.2_08-b03 mixed mode):

"Signal Dispatcher" daemon prio=1 tid=0x0925d8d8 nid=0x3eea runnable [0..0]

"Finalizer" daemon prio=1 tid=0x09248e38 nid=0x3eea in Object.wait() [5a6000..5a6228]
        at java.lang.Object.wait(Native Method)
        - waiting on <0xae3573f0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:111)
        - locked <0xae3573f0> (a java.lang.ref.ReferenceQueue$Lock)
        at java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:127)
        at java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:159)

"Reference Handler" daemon prio=1 tid=0x09248290 nid=0x3eea in Object.wait() [4eb000..4eb228]
        at java.lang.Object.wait(Native Method)
        - waiting on <0xae357290> (a java.lang.ref.Reference$Lock)
        at java.lang.Object.wait(Object.java:429)
        at java.lang.ref.Reference$ReferenceHandler.run(Reference.java:115)
        - locked <0xae357290> (a java.lang.ref.Reference$Lock)

"main" prio=1 tid=0x092129a0 nid=0x3eea waiting on condition [bff37000..bff3729c]
        at java.lang.Thread.sleep(Native Method)
        at CopyToTest.main(CopyToTest.java:27)

"VM Thread" prio=1 tid=0x09247030 nid=0x3eea runnable 

"VM Periodic Task Thread" prio=1 tid=0x092600d8 nid=0x3eea waiting on condition 
"Suspend Checker Thread" prio=1 tid=0x0925cf20 nid=0x3eea runnable

Now you can see only VM threads are left.

AFAICT everything is working perfectly.

Or just try to add a 20 second sleep to your test and you'll see the
Transport threads exit. You can make them close quicker by reducing
jcifs.smb.client.soTimeout.

Mike

[1] To get a thread dump on Windows, run your program on the console
and press <ctrl><break> (on Unix it's <ctrl>\).

On Fri, 24 Nov 2006 09:42:37 +0100
"Tim Struyf" <tim.struyf at roots.be> wrote:

> Dear,
> 
>  
> 
> Here is a stacktrace,
> 
> If you get this exception, then the writer thread won't get closed
> correctly. 
> 
>  
> 
>  
> 
> jcifs.smb.SmbException: The system cannot find the file specified.
> 
>       at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:511)
> 
>       at jcifs.smb.SmbTransport.send(SmbTransport.java:588)
> 
>       at jcifs.smb.SmbSession.send(SmbSession.java:239)
> 
>       at jcifs.smb.SmbTree.send(SmbTree.java:109)
> 
>       at jcifs.smb.SmbFile.send(SmbFile.java:690)
> 
>       at jcifs.smb.SmbFile.queryPath(SmbFile.java:1202)
> 
>       at jcifs.smb.SmbFile.copyTo0(SmbFile.java:1950)
> 
>       at jcifs.smb.SmbFile.copyTo(SmbFile.java:2140)
> 
>       at jcifs.test.JCifsTest.testCopy(JCifsTest.java:41)
> 
>       at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
> 
>       at
> sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.jav
> a:39)
> 
>       at
> sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessor
> Impl.java:25)
> 
>       at java.lang.reflect.Method.invoke(Method.java:324)
> 
>       at junit.framework.TestCase.runTest(TestCase.java:154)
> 
>       at junit.framework.TestCase.runBare(TestCase.java:127)
> 
>       at junit.framework.TestResult$1.protect(TestResult.java:106)
> 
>       at junit.framework.TestResult.runProtected(TestResult.java:124)
> 
>       at junit.framework.TestResult.run(TestResult.java:109)
> 
>       at junit.framework.TestCase.run(TestCase.java:118)
> 
>       at junit.framework.TestSuite.runTest(TestSuite.java:208)
> 
>       at junit.framework.TestSuite.run(TestSuite.java:203)
> 
>       at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTe
> stRunner.java:478)
> 
>       at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRun
> ner.java:344)
> 
>       at
> org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRu
> nner.java:196)
> 
> jcifs.smb.SmbException: The system cannot find the file specified.
> 
>       at jcifs.smb.SmbTransport.checkStatus(SmbTransport.java:511)
> 
>       at jcifs.smb.SmbTransport.send(SmbTransport.java:588)
> 
>       at jcifs.smb.SmbSession.send(SmbSession.java:239)
> 
>       at jcifs.smb.SmbTree.send(SmbTree.java:109)
> 
>       at jcifs.smb.SmbFile.send(SmbFile.java:690)
> 
>  
> 
>  
> 
> You will get this when you put up a share, and try to copy a file that
> does NOT exist from this share to another share.
> 
> The JCIFS writerthreads should be closed when such a thing happens. In
> the current version, the writer threads aren't closed, so the test case
> below will cause 1000 writer threads to be locked... 
> 
>  
> 
>  
> 
> for(int i = 0; i < 1000; i++) {
> 
>       try {
> 
>             SmbFile file = JCifsUtil.getSmbFileFor(
> "myComputer/someShare/doesNotExist.txt" );
> 
>             SmbFile to  = JCifsUtil.getSmbFileFor(
> "anotherComputer/someShare/doesNotExist.txt");
> 
>             file.copyTo(to);
> 
>       } catch (Exception e) {
> 
>             e.printStackTrace();
> 
>       }
> 
>       /* put breakpoint up here, you will see 1000 writer threads in
> wait state */
> 
> }
> 
>  
> 
> JCifsUtil is just a small class which returns an SmbFile for the given
> input.
> 
>  
> 
> regards,
> 
> Tim
> 
>  
> 
> Tim Struyf
> 
> Consultant,
> 
>  
> 
> Roots Software
> 
> Oudestraat 113 * 2630 Aartselaar * Belgium
> 
> Email: tim.struyf at roots.be
> 
> http://www.roots.be 
> 
>  
> 
> -----Original Message-----
> From: Michael B Allen [mailto:mba2000 at ioplex.com] 
> Sent: dinsdag 21 november 2006 17:56
> To: Tim Struyf
> Cc: jcifs at lists.samba.org; contact! Support
> Subject: Re: [jcifs] bugs in JCIFS 1.2.9
> 
>  
> 
> Using interrupt should not be necessary. I was not able to reproduce
> 
> this issue. If a WriterThread is blocked trying to write than you need
> 
> to figure out why. What is the Exception that is being thrown in your
> 
> catch that issues the interrupt?
> 
>  
> 
> If there is a bug in the logic then I would be happy to fix that but I
> 
> fail to see WHY you think interrupt() should be necessary.
> 
>  
> 
> Can you provide a thread dump?
> 
>  
> 
> Mike
> 
>  
> 
> On Wed, 15 Nov 2006 15:35:36 +0100
> 
> "Tim Struyf" <tim.struyf at roots.be> wrote:
> 
>  
> 
> > Dear,
> 
> >  
> 
> > This issue isnt fixed in JCIFS 1.2.10...
> 
> > I still see a lot of writer threads that stay in their locked state in
> the new version...
> 
> >  
> 
> > I thinkt the w.interrupt is realy required to fix this issue...
> 
> >  
> 
> > see attached screenshot
> 
> >  
> 
> > regards,
> 
> > Tim
> 
> > 
> 
> > ________________________________
> 
> > 
> 
> > From: Michael B Allen [mailto:mba2000 at ioplex.com]
> 
> > Sent: Mon 13/11/2006 5:40 PM
> 
> > To: Tim Struyf; jcifs at lists.samba.org; contact! Support
> 
> > Subject: Re: [jcifs] bugs in JCIFS 1.2.9
> 
> > 
> 
> > 
> 
> > 
> 
> > This has been fixed. If the copyTo0 fails a finally has been added to
> 
> > guarantee files are closed. Another finally has been added to copyTo()
> 
> > that guarantees that the stop write signals the WriterThread to wake
> up
> 
> > and exit (if the WriterThread is stuck trying to read this will have
> no
> 
> > effect, it does not use interrupt()).
> 
> > 
> 
> > Mike
> 
> > 
> 
> > On Wed, 8 Nov 2006 13:03:42 -0500
> 
> > Michael B Allen <mba2000 at ioplex.com> wrote:
> 
> > 
> 
> > > Yes, I believe this is all the same bug someone reported before. The
> 
> > > bug is because of a big try catch added to SmbFile.copyTo0 during
> some
> 
> > > debugging. Try to remove/move the try catch to look like the below:
> 
> > > And please let me know if it works. I'm going to do an update soon.
> 
> > >
> 
> > >    1972             }
> 
> > >    1973         } else {
> 
> > >    1974             int off;
> 
> > >    1975
> 
> > >    1976             try {
> 
> > >    1977                 open( SmbFile.O_RDONLY, 0, ATTR_NORMAL, 0 );
> 
> > >    1978                 try {
> 
> > >    ....
> 
> > >    2022                 dest.send( new Trans2SetFileInformation(
> 
> > >    2023                         dest.fid, attributes, createTime,
> lastModified ),
> 
> > >    2024                         new
> Trans2SetFileInformationResponse() );
> 
> > >    2025                 dest.close( 0L );
> 
> > >    2026             } catch( Exception ex ) {
> 
> > >    2027                 if( log.level > 1 )
> 
> > >    2028                     ex.printStackTrace( log );
> 
> > >    2029             } finally { <<---- important to always close!
> 
> > >    2030                 close();
> 
> > >    2031             }
> 
> > >    2032         }
> 
> > >    2033     }
> 
> > >    2034 /**
> 
> > >
> 
> > >
> 
> > > On Wed, 8 Nov 2006 17:00:18 +0100
> 
> > > "Tim Struyf" <tim.struyf at roots.be> wrote:
> 
> > >
> 
> > > > Dear,
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > > I found a bug in JCIFS 1.2.9
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > > Apparently when trying to copy a file that does not exist the
> 
> > > > writerthread isn't closed.
> 
> > > >
> 
> > > > Thus causing problems with a lot of writerthreads that are and
> remain in
> 
> > > > the "wait" state
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > > For example if you execute this testcase with version 1.2.9 you
> will get
> 
> > > > 1000 writer threads in the "wait" state
> 
> > > >
> 
> > > > Important is that you have a share and try to open a file that
> does not
> 
> > > > exist, you will get a stacktrace printed in your console ... but
> the
> 
> > > > writer thread stays open...
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > > public class JCifsTest extends TestCase {
> 
> > > >
> 
> > > > public void testCopy() {
> 
> > > >
> 
> > > >                         for(int i = 0; i < 1000; i++) {
> 
> > > >
> 
> > > >                                     try {
> 
> > > >
> 
> > > >                                                 SmbFile file
> 
> > > > = JCifsUtil.getSmbFileFor(
> "myComputer/someShare/fileDoesNotExist.txt"
> 
> > > > );
> 
> > > >
> 
> > > >                                                 SmbFile to
> 
> > > > = JCifsUtil.getSmbFileFor(
> "myComputer/someShare/fileDoesNotExist.txt");
> 
> > > >
> 
> > > >                                                 file.copyTo(to);
> 
> > > >
> 
> > > >                                     } catch (Exception e) {
> 
> > > >
> 
> > > >
> e.printStackTrace();
> 
> > > >
> 
> > > >                                     }
> 
> > > >
> 
> > > >                         }
> 
> > > >
> 
> > > >                         //put a breakpoint up here and see... 1000
> 
> > > > writer threads waiting...
> 
> > > >
> 
> > > >                         System.out.println("boom!");
> 
> > > >
> 
> > > >             }                      
> 
> > > >
> 
> > > > }
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > > I fixed this by adding a try catch clause in the copyTo method in
> 
> > > > SmbFile.java
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > >        /** copy to method.... **/
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > >         w = new WriterThread();
> 
> > > >
> 
> > > >         w.setDaemon( true );
> 
> > > >
> 
> > > >         w.start();
> 
> > > >
> 
> > > >             //added a try catch block
> 
> > > >
> 
> > > >         try {
> 
> > > >
> 
> > > >                     /* Downgrade one transport to the lower of the
> 
> > > > negotiated buffer sizes
> 
> > > >
> 
> > > >                      * so we can just send whatever is received.
> 
> > > >
> 
> > > >                      */
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > >                     SmbTransport t1 = tree.session.transport;
> 
> > > >
> 
> > > >                     SmbTransport t2 = dest.tree.session.transport;
> 
> > > >
> 
> > > >            
> 
> > > >
> 
> > > >                     if( t1.snd_buf_size < t2.snd_buf_size ) {
> 
> > > >
> 
> > > >                         t2.snd_buf_size = t1.snd_buf_size;
> 
> > > >
> 
> > > >                     } else {
> 
> > > >
> 
> > > >                         t1.snd_buf_size = t2.snd_buf_size;
> 
> > > >
> 
> > > >                     }
> 
> > > >
> 
> > > >            
> 
> > > >
> 
> > > >                     bsize = Math.min( t1.rcv_buf_size - 70,
> 
> > > > t1.snd_buf_size - 70 );
> 
> > > >
> 
> > > >                     b = new byte[2][bsize];
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > >             copyTo0( dest, b, bsize, w, req, resp );
> 
> > > >
> 
> > > >             w.write( null, -1, null, 0 );
> 
> > > >
> 
> > > >        } catch (Exception e ){
> 
> > > >
> 
> > > >             //stop the writer thread! If we get an exception
> 
> > > >
> 
> > > >             e.printStackTrace();
> 
> > > >
> 
> > > >             w.interrupt();
> 
> > > >
> 
> > > >        }
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > > Another bug was already posted here.
> 
> > > >
> 
> > > > If you try to copy a file to a share on which you don't have
> access
> 
> > > > rights, this fails but the writer threads don't close... also the
> source
> 
> > > > file you are copying from cant be deleted... because its in use...
> (by
> 
> > > > the writerthread that's locked...)
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > > public void testCopyAndDelete() throws SmbException {
> 
> > > >
> 
> > > >                         for(int i = 0; i < 1000; i++) {
> 
> > > >
> 
> > > >                                     try {
> 
> > > >
> 
> > > >                                                 SmbFile file
> =
> 
> > > > JCifsUtil.getSmbFileFor( "myComputer/myShare/someFile.txt" );
> 
> > > >
> 
> > > > 
> 
> > > > System.out.println(file.getUncPath() + " exists: " +
> file.exists());
> 
> > > >
> 
> > > >                                                 SmbFile to
> 
> > > > = JCifsUtil.getSmbFileFor(
> 
> > > > "myComputer/ShareOnWhichIDontHaveAccessRights/someFile.txt");
> 
> > > >
> 
> > > > 
> 
> > > > System.out.println(to.getUncPath() + " exists: "    +
> to.exists());
> 
> > > >
> 
> > > >                                                 file.copyTo( to );
> 
> > > >
> 
> > > >                                                 file.delete();
> 
> > > >
> 
> > > >                                     } catch (Exception e) {
> 
> > > >
> 
> > > >
> e.printStackTrace();
> 
> > > >
> 
> > > >                                     }
> 
> > > >
> 
> > > >                         }
> 
> > > >
> 
> > > >             }
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > > In version 1.2.9 of JCIFS this code will cause the errors
> described
> 
> > > > above, a lot of writer threads that are locked + files that are in
> use,
> 
> > > > and cant be deleted...
> 
> > > >
> 
> > > > I fixed this by changing the copyTo0 method in SmbFile.java
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > >                                                 dest.send( new
> 
> > > > Trans2SetFileInformation(dest.fid, attributes, createTime,
> lastModified
> 
> > > > ),  new Trans2SetFileInformationResponse() );
> 
> > > >
> 
> > > >                                                 dest.close( 0L );
> 
> > > >
> 
> > > >                                     } catch( Exception ex ) {
> 
> > > >
> 
> > > >                                                 //stop the
> writerthreads
> 
> > > >
> 
> > > >                                                 w.interrupt();
> 
> > > >
> 
> > > >                                                 if( log.level > 1
> )
> 
> > > >
> 
> > > > 
> 
> > > > ex.printStackTrace( log );
> 
> > > >
> 
> > > >                                     } finally {
> 
> > > >
> 
> > > >                                                 //added a finally
> clause
> 
> > > >
> 
> > > >                                                 close();
> 
> > > >
> 
> > > >                                     }
> 
> > > >
> 
> > > > Best regards,
> 
> > > >
> 
> > > > Tim
> 
> > > >
> 
> > > > groetjes,
> 
> > > >
> 
> > > > Tim Struyf
> 
> > > > Consultant,
> 
> > > >
> 
> > > > Roots Software
> 
> > > > Oudestraat 113 * 2630 Aartselaar * Belgium
> 
> > > > Phone + 32 3 870 71 11 * Fax + 32 3 870 71 19
> 
> > > > Email: tim.struyf at roots.be <mailto:tim.struyf at roots.be>
> 
> > > > http://www.roots.be
> 
> > > >
> 
> > > > 
> 
> > > >
> 
> > > >
> 
> > >
> 
> > >
> 
> > > --
> 
> > > Michael B Allen
> 
> > > PHP Active Directory SSO
> 
> > > http://www.ioplex.com/
> 
> > >
> 
> > 
> 
> > 
> 
> > --
> 
> > Michael B Allen
> 
> > PHP Active Directory SSO
> 
> > http://www.ioplex.com/
> 
> > 
> 
> > 
> 
> > 
> 
>  
> 
>  
> 
> -- 
> 
> Michael B Allen
> 
> PHP Active Directory SSO
> 
> http://www.ioplex.com/
> 
> 


-- 
Michael B Allen
PHP Active Directory SSO
http://www.ioplex.com/


More information about the jcifs mailing list