You are viewing a plain text version of this content. The canonical link for it is here.
Posted to issues@commons.apache.org by "Johannes Scharf (JIRA)" <ji...@apache.org> on 2010/01/08 14:12:54 UTC

[jira] Issue Comment Edited: (VFS-294) FtpFileObject is not threadsafe

    [ https://issues.apache.org/jira/browse/VFS-294?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=12798005#action_12798005 ] 

Johannes Scharf edited comment on VFS-294 at 1/8/10 1:12 PM:
-------------------------------------------------------------

After hours of research I think I've found a possible solution for this bug. The "getInfo" method in FtpFileObject gets called from multiple locations inside the class but is not synchronized at all.
I've synchronized on the "ftpFs" object as synchronizing on "this" causes a deadlock. Several tests with 10 to 20 threads were made without any errors.

Finally
{code:java}
	 private void getInfo(boolean flush) throws IOException
    {
        final FtpFileObject parent = (FtpFileObject) FileObjectUtils.getAbstractFileObject(getParent());
        FTPFile newFileInfo;
        if (parent != null)
        {
            newFileInfo = parent.getChildFile(UriParser.decode(getName().getBaseName()), flush);
        }
        else
        {
            // Assume the root is a directory and exists
            newFileInfo = new FTPFile();
            newFileInfo.setType(FTPFile.DIRECTORY_TYPE);
        }

        this.fileInfo = newFileInfo;
    }
{code}
must be changed to:
{code:java}
	private void getInfo(boolean flush) throws IOException {
		synchronized (ftpFs) {
			final FtpFileObject parent = (FtpFileObject) FileObjectUtils
					.getAbstractFileObject(getParent());
			FTPFile newFileInfo;
			if (parent != null) {
				newFileInfo = parent.getChildFile(UriParser.decode(getName()
						.getBaseName()), flush);
			} else {
				// Assume the root is a directory and exists
				newFileInfo = new FTPFile();
				newFileInfo.setType(FTPFile.DIRECTORY_TYPE);
			}

			this.fileInfo = newFileInfo;
		}
	}
{code}

I'll provide a subversion patch in the future, when I've got some time left.


      was (Author: scharfj):
    After hours of research I think I've found a possible solution for this bug. The "getInfo" method in FtpFileObject gets called from multiple locations inside the class but is not synchronized at all.
I've synchronized on the "ftpFs" object as synchronizing on "this" causes a deadlock. Several tests with 10 to 20 threads were made without any errors.

Finally
{code:java}
	 private void getInfo(boolean flush) throws IOException
    {
        final FtpFileObject parent = (FtpFileObject) FileObjectUtils.getAbstractFileObject(getParent());
        FTPFile newFileInfo;
        if (parent != null)
        {
            newFileInfo = parent.getChildFile(UriParser.decode(getName().getBaseName()), flush);
        }
        else
        {
            // Assume the root is a directory and exists
            newFileInfo = new FTPFile();
            newFileInfo.setType(FTPFile.DIRECTORY_TYPE);
        }

        this.fileInfo = newFileInfo;
    }
{/code}
must be changed to:
{code:java}
	private void getInfo(boolean flush) throws IOException {
		synchronized (ftpFs) {
			final FtpFileObject parent = (FtpFileObject) FileObjectUtils
					.getAbstractFileObject(getParent());
			FTPFile newFileInfo;
			if (parent != null) {
				newFileInfo = parent.getChildFile(UriParser.decode(getName()
						.getBaseName()), flush);
			} else {
				// Assume the root is a directory and exists
				newFileInfo = new FTPFile();
				newFileInfo.setType(FTPFile.DIRECTORY_TYPE);
			}

			this.fileInfo = newFileInfo;
		}
	}
{/code}

I'll provide a subversion patch in the future, when I've got some time left.

  
> FtpFileObject is not threadsafe
> -------------------------------
>
>                 Key: VFS-294
>                 URL: https://issues.apache.org/jira/browse/VFS-294
>             Project: Commons VFS
>          Issue Type: Bug
>    Affects Versions: 1.0
>            Reporter: Johannes Scharf
>
> During my efforts to find a solution for VFS-293 I've discovered another bug regarding threadsafety.
> It seems that FtpFileObject is at least not fully threadsafe. When a FtpFileObject is accessed by multiple threads from time to time closing the OutputStream for a file fails with a NullPointerException.
> Stacktrace:
> {noformat}
>  org.apache.commons.vfs.FileSystemException: Could not close the output stream for file "ftp://localhost/spring-framework-2.5.5/dist/resources/spring-jms-2.5.xsd".
> 	at org.apache.commons.vfs.provider.DefaultFileContent$FileContentOutputStream.close(DefaultFileContent.java:599)
> 	at at.js.jtransporter.transporter.VFSTransporter$VFSOutputStream.close(VFSTransporter.java:219)
> 	at at.js.jtransporter.util.Utils.close(Utils.java:40)
> 	at at.js.jtransporter.worker.resource.ResourceWorker.createFile(ResourceWorker.java:108)
> 	at at.js.jtransporter.worker.resource.ResourceWorker.processJob(ResourceWorker.java:52)
> 	at at.js.jtransporter.worker.AbstractRunnableWorker.run(AbstractRunnableWorker.java:82)
> 	at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:885)
> 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:907)
> 	at java.lang.Thread.run(Thread.java:619)
> Caused by: org.apache.commons.vfs.FileSystemException: Could not close the output stream for file "ftp://localhost/spring-framework-2.5.5/dist/resources/spring-jms-2.5.xsd".
> 	at org.apache.commons.vfs.provider.DefaultFileContent$FileContentOutputStream.onClose(DefaultFileContent.java:620)
> 	at org.apache.commons.vfs.util.MonitorOutputStream.close(MonitorOutputStream.java:63)
> 	at org.apache.commons.vfs.provider.DefaultFileContent$FileContentOutputStream.close(DefaultFileContent.java:595)
> 	... 8 more
> Caused by: java.lang.NullPointerException
> 	at org.apache.commons.vfs.provider.ftp.FtpFileObject.getChildFile(FtpFileObject.java:106)
> 	at org.apache.commons.vfs.provider.ftp.FtpFileObject.getInfo(FtpFileObject.java:181)
> 	at org.apache.commons.vfs.provider.ftp.FtpFileObject.onChange(FtpFileObject.java:269)
> 	at org.apache.commons.vfs.provider.AbstractFileObject.endOutput(AbstractFileObject.java:1325)
> 	at org.apache.commons.vfs.provider.DefaultFileContent.endOutput(DefaultFileContent.java:459)
> 	at org.apache.commons.vfs.provider.DefaultFileContent.access$200(DefaultFileContent.java:44)
> 	at org.apache.commons.vfs.provider.DefaultFileContent$FileContentOutputStream.onClose(DefaultFileContent.java:616)
> 	... 10 more
> {noformat}

-- 
This message is automatically generated by JIRA.
-
You can reply to this email to add a comment to the issue online.