views:

224

answers:

2

I have a rake task that uploads a list of files via ftp. Copying without threading works fine, but it would be faster if I could do multiple concurrent uploads. (I'm new to ruby and multithreading, so no surprise it didn't work right off the bat.)

I have:

files.each_slice(files.length / max_threads) do |file_set|
    threads << Thread.new(file_set) do |file_slice|
        running_threads += 1
        thread_num = running_threads
        thread_num.freeze
        puts "making thread # #{thread_num}"

        file_slice.each do |file|
            file.freeze
            if File.directory?(file) 
            else
                puts file.pathmap("#{$ftpDestination}%p")
                ftp.putbinaryfile(file, file.pathmap("#{$ftpDestination}%p")) 
            end
        end
    end    
end

My output is:

making thread # 1
/test/./1column-ff-template.aspx
making thread # 2
making thread # 3
/test/./admin/footerContent.aspx
/test/./admin/contentList.aspx
making thread # 4
/test/./3columnTemplate.ascx
making thread # 5
/test/./ascx/dashboard/dash.ascx
making thread # 6
/test/./ascx/Links.ascx
making thread # 7
/test/./bin/App_GlobalResources.dll
making thread # 8
/test/./bin/App_Web__foxtqrr.dll
making thread # 9
/test/./GetPageLink.ascx

So it looks like each thread starts to upload a file and then dies without an error. What am I doing wrong?

+2  A: 

If abort_on_exception is false and the debug flag is not enabled (default) an unhandled exception kills the current thread. You don't even know about it until you issue a join on the thread that raised it. So you can do a join or change the debug flag and you should get the exception if one is indeed thrown.

JRL
Great! I didn't even know about the debug flag.
willoller
@JRL: Added $DEBUG=true, and abort_on_exception. I got to the error, which is "IOError stream closed". I thought it was a locking issue, but it happens even when I have only 1 thread - any other advice?Thanks!
willoller
@willoller: are you calling File.open with an associated block? If so, the file will automatically be closed when the block terminates. If you don't want this, do not associate a block with the File.open method call, or use File.new.
JRL
Found the solution to the second problem, and added an answer. Thanks!
willoller
A: 

The root of the problem was fixed by adding:

threads.each { |t| t.join }

after the file_slice loop ends.

Thanks to JRL for helping me find the Exception!

willoller