--- panels/panels_ipe/js/panels_ipe.js
+++ panels/panels_ipe/js/panels_ipe.js
@@ -82,11 +82,11 @@
       ipe.cancelLock();
     }
   });
 
   // If a user navigates away from a locked IPE, cancel the lock in the background.
-  $(window).bind('unload', function() {
+  $(window).bind('beforeunload', function() {
     ipe.cancelLock(true);
   });
 
   /**
    * If something caused us to abort what we were doing, send a background

--- panels/panels_ipe/plugins/display_renderers/panels_renderer_ipe.class.php
+++ panels/panels_ipe/plugins/display_renderers/panels_renderer_ipe.class.php
@@ -207,12 +207,13 @@
    * It has no visible return value as this is considered a background task
    * and the client side has already given all indications that things are
    * now in a 'normal' state.
    */
   function ajax_unlock_ipe() {
-    panels_edit_cache_clear($this->cache);
     $this->commands[] = array();
+    $this->cache->ipe_locked = NULL;
+    panels_edit_cache_set($this->cache);
   }
 
   /**
    * AJAX entry point to create the controller form for an IPE.
    */
@@ -237,11 +238,11 @@
       panels_edit_cache_set($this->cache);
       $this->commands[] = array(
         'command' => 'initIPE',
         'key' => $this->clean_key,
         'data' => drupal_render($output),
-        'lockPath' => $this->get_url('unlock_ipe'),
+        'lockPath' => base_path() . $this->get_url('unlock_ipe'),
       );
       return;
     }
 
     // Check to see if we have a lock that was broken. If so we need to
@@ -263,12 +264,13 @@
       // rendered.
       $this->meta_location = 'inline';
       $this->commands[] = ajax_command_replace("#panels-ipe-display-{$this->clean_key}", panels_render_display($this->display, $this));
     }
     else {
-      // Cancelled. Clear the cache.
-      panels_edit_cache_clear($this->cache);
+      // Cancelled. Release the lock.
+      $this->cache->ipe_locked = NULL;
+      panels_edit_cache_set($this->cache);
     }
 
     $this->commands[] = array(
       'command' => 'endIPE',
       'key' => $this->clean_key,
@@ -308,11 +310,11 @@
 
     $this->commands[] = ctools_modal_command_display(t('Change layout'), $output);
     $this->commands[] = array(
       'command' => 'IPEsetLockState',
       'key' => $this->clean_key,
-      'lockPath' => $this->get_url('unlock_ipe'),
+      'lockPath' => base_path() . $this->get_url('unlock_ipe'),
     );
   }
 
   function ajax_set_layout($layout) {
     ctools_include('context');
@@ -332,10 +334,11 @@
       }
 
       if (!empty($form_state['clicked_button']['#save-display'])) {
         // Saved. Save the cache.
         panels_edit_cache_save($this->cache);
+        panels_edit_cache_set($this->cache);
         $this->display->skip_cache;
 
         // Since the layout changed, we have to update these things in the
         // renderer in order to get the right settings.
         $layout = panels_get_layout($this->display->layout);
