Stop frozen method

I originally posted this in my library’s thread in Networking & Multiplayer, but this is a complicated issue that if anyone else encounters will likely want to find the answer easily, so I made this thread. I was working today on fixing the issue where my auto-updater/patcher freezes when internet connection is lost in the middle of a download, and I came up with a solution that seemed to work. The download would be run on a separate thread and if the thread takes longer to finish than expected the internet connection would be checked and if there is not internet then “return;” would be called in the method after something was printed to the console about how the download was aborted due to internet being lost. This is the code:


		ReadableByteChannel rbc = null;
		FileOutputStream fos = null;
		try {
//			creates file in temporary directory to be downloaded to, so that the main file isn't lost if the download is aborted
			File temp = File.createTempFile("tempFile", filePath.substring(filePath.lastIndexOf('.'), filePath.length()));
//			the file will be deleted upon exit unless the download is aborted mid-way
			temp.deleteOnExit();
			URL file = new URL(fileSite);
			URLConnection urlconnection = file.openConnection();
			urlconnection.setReadTimeout(5000);
			long size = urlconnection.getContentLength();
			rbc = Channels.newChannel(file.openStream());
			fos = new FileOutputStream(temp);
			long position = 0;
			if(usingChunks)
				while(position < size){
					if(!hasInternet)
						return;
//					downloads chunkSize bytes and increases the position on the download accordingly
					final long finalPosition = position;
					final FileOutputStream finalFos = fos;
					final ReadableByteChannel finalRbc = rbc;
					Thread download = new Thread(new Runnable(){
						public void run(){
							try {
								if(hasInternet)
									finalFos.getChannel().transferFrom(finalRbc, finalPosition, chunkSize);
							} catch (IOException e) {
								e.printStackTrace();
							}
						}
					});
					download.start();
					long timeout = chunkSize;
					try {
						download.join(timeout);
					} catch (InterruptedException e) {
						ErrorLogger.logError(e);
						return;
					}
					if(download.isAlive())
						if(!isInternetReachable())
							if(!hasInternetFallback()){
//								this is a nested if because I only want to check internet if the above requirement works because checking internet takes some time
								System.out.println("Internet connection lost");
								hasInternet = false;
								return;
							}
					position += chunkSize;
//					position += fos.getChannel().transferFrom(rbc, position, chunkSize);
//					sets progress to the nearest tenth of the amount of bytes downloaded out of the total
					progress = Math.round((float)(100 * (float)position / (float)size) * (float)10) / (float)10;
					System.out.println(progress + "% done");
				}

The error is that if internet connection is lost the transferFrom method keeps running and running and running and running and running… It just doesn’t stop. I really wish it would throw an exception but it just keeps running. This makes it so that when the checkForUpdate() method (the method from which the excerpt that is posted is from) tries to stop, the thread still running prevents the main method that called checkForUpdate() to advance further down the code line (which in my main method for testing would involve launching the extracted zip file’s jar). Do you know how I can fix this? After searching on Google for an hour or two, I’m completely clueless.

hi,

try this…


URLConnection urlconnection = file.openConnection();
urlconnection.setReadTimeout(5000);
long size = urlconnection.getContentLength();

URLConnection’s read-timeout is set to 0 by default, which means ‘wait forever’.

No difference is made, after calling “return;” the method is still frozen.

The shown threading makes no sense to me. You first start a download thread, but then pause the further process until it died again. So, what was the reason to spawn a separate thread ? After it died, you ask if it is still alive, which is never the case, to decide what to do next.

I thought that the join() method made the currently ran thread (the one running the while loop) wait for the thread download to die and if it didn’t die within the timeout argument then the currently ran thread would carry on. Then I would check if it is alive (normally it wouldn’t be) and if it is then it didn’t download in the expected time so I would confirm that there is indeed internet and if not I would quit the method. It worked completely fine, as when internet connection was lost the console would print “Internet connection lost”, so I believe it is programmed right. It’s just the transferFrom() method screwing it all up.

I did not recognize the timeout parameter maybe because you use the chunk size for it, instead of a time span ?
Still, it is a rather strange workaround to me to use a thread here. Broken connections should be notified by catching appropriate exceptions or setting connections timeouts. If that doesn’t work, then there is another basic bug hiding out somewhere, I guess.

As far as I know transferFrom does not seem to throw any exceptions when it can’t connect to get the bytes, it seems to just keep trying and freeze. Thus, I can’t catch appropriate exceptions and connection timeouts don’t seem to work. Also, I used chunkSize as the timeout because I assume 1 byte a millisecond for a download is a slow internet speed today. Maybe I should use another method instead of transferFrom to download so that it doesn’t freeze, but I’m not sure if a different method won’t freeze either.

Can’t comment on transferFrom without trying, maybe you are feeding wrong positions or chunk sizes.
That timeout calculation assumption is weird, should definitely be replaced.

Both position and chunkSize are correct throughout the download. What would you rather have the timeout be? I’d prefer to utilize chunkSize in some way so that the timeout relates to how long the download is, for example, if the file is 200 MB I don’t want the timeout to be 1000 or 2000 because then it will check for internet when it shouldn’t.

Might I go out on a limb and suggest a separate variable named something like, oh, [icode]timeout[/icode]?

I have made a separate long named timeout. This doesn’t solve the error however, it still freezes.

???
Why not just create the urlconmection, set the timeout, and then call tarnsferfrom with the whole content length?
It doesn’t look like you’re monitoring download progress anywhere.

It’s in a while loop where it downloads chunkSize bytes each time in the loop and then calculates the percentage because it has retrieved from the URLConnection how big the file is. There’s also a method for downloading it all at once that I should try to apply that too and see if it works.

I tested it without calculating percentages and it still freezes when internet is lost. Does anyone have any ideas? Maybe I need to rewrite the whole process of downloading.

Could it be a problem with the transfer from method? Try using a byte buffer with .read() and .write().

I thought that could be the problem and so I will try out that method. I’ll see how well it works and if it doesn’t freeze then I will use that as my new download method.

EDIT: It still freezes so I will deem this as unsolvable for the time being.