Commits

Joe Clark committed 964b317

Avoid infinite loop within install Task.

Comments (0)

Files changed (1)

src/main/java/com/atlassian/bamboo/plugins/confdeploy/UniversalPluginUploader.java

 
 import com.atlassian.bamboo.build.logger.BuildLogger;
 import com.atlassian.bamboo.task.TaskException;
+import com.atlassian.util.concurrent.Timeout;
 import org.apache.http.Header;
 import org.apache.http.HttpEntity;
 import org.apache.http.HttpResponse;
 import java.io.IOException;
 import java.io.UnsupportedEncodingException;
 import java.util.Random;
+import java.util.concurrent.TimeUnit;
 
 /**
  * A helper class capable of submitting a plugin upload to a REST resource provided by Atlassian's Universal Plugin Manager.
         {
             JSONObject response = new JSONObject(entity);
 
+            // This loop could execute indefinitely if the UPM on the remote server misbehaves and never returns an
+            // appropriate error response. To guard against this happening, only let this loop execute for a maximum of
+            // ~1 minute. Generally speaking, the Atlassian plugins framework grants a grace period of 60 seconds for a
+            // plugin to finish enabling. If we've been going longer than this, there's a good chance the plugin did
+            // not install successfully. We'll allow for 60 seconds, plus a little extra for the actual upload to happen,
+            // before terminating this loop.
+            Timeout timeout = Timeout.getMillisTimeout(90, TimeUnit.SECONDS);
             //no more polling is needed if there is no pingAfter value
-            if (response.has("pingAfter"))
+            while (response.has("pingAfter"))
             {
                 Thread.sleep(response.getInt("pingAfter"));
 
                 EntityUtils.consume(polledResponse.getEntity());
 
                 int statusCode = status.getStatusCode();
+                if (timeout.isExpired())
+                {
+                    throw new TaskException("Plugin upload did not succeed within the timeout.");
+                }
                 if (statusCode == 200) //200 indicates the process is ok and ongoing.
                 {
-                    poll(polledEntity, baseUrl, client);
+                    response = new JSONObject(polledEntity);
                 }
                 else if (statusCode >= 400)
                 {
                 else
                 {
                     buildLogger.addBuildLogEntry("Plugin upload completed!");
+                    break;
                 }
             }
         }