I recently upgraded a site to 8.4.0. Beforehand I put the site in maintenance mode. I ran `drush updb` per usual and found that after it was done, the site was no longer in maintenance mode.

After some digging I believe the reason is that there was an update hook that involved a batch process. The batch process code automatically puts the site into maintenance mode and stores the current state of maintenance mode in a session variable. Then, after the batch process is complete, it sets maintenance mode back to what it was before by inspecting the session variable.

Problem is that there's no session state when the process is run via drush. I guess it works fine if the updates are run via update.php.

The code that sets stores the state is in DbUpdateController, in the method "triggerBatch".

Can we store the maintenance mode state in a different temporary state variable instead of session storage?

Comments

bkosborne created an issue. See original summary.

Version: 8.5.x-dev » 8.6.x-dev

Drupal 8.5.0-alpha1 will be released the week of January 17, 2018, which means new developments and disruptive changes should now be targeted against the 8.6.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

Wim Leers’s picture

Category: Feature request » Support request
Status: Active » Fixed

Maintenance mode is not only stored in the current session; it's stored in the State service. That's actually what happens: triggerBatch() reads the current maintenance mode state from State, stores this in the session, then enables maintenance mode regardless of prior state, and after finishing the update batch, it restores the prior state.


There were known issues with certain Drush versions in combination with Drupal 8.4 (because 8.4 updated certain Symfony components because Symfony required Drupal to do so).

Are you sure that's not what happened?


Given ~6 months have passed and nobody else has reported this, I'm going to close this and assume that that's what happened. If you reopen, please provide concrete steps to reproduce.

bkosborne’s picture

Status: Fixed » Active

I'll try and come up with a test case for this to demonstrate.

and after finishing the update batch, it restores the prior state.

But it does so with this code:

  // Now that the update is done, we can put the site back online if it was
  // previously not in maintenance mode.
  if (empty($_SESSION['maintenance_mode'])) {
    \Drupal::state()
      ->set('system.maintenance_mode', FALSE);
  }
  unset($_SESSION['maintenance_mode']);

But when the batch process runs via drush, I think that the global $_SESSION var is not reliable. There's no session cookie or anything to store the session ID with when the batch process starts - unless Drush has some workaround for that?

So, from that code, you can see that it defaults to taking a site OUT of maintenance mode if the previous state is undefined

bkosborne’s picture

Reproduce:

1) Drupal 8.5.3, Drush 8.1.16
2) Create custom module "batch_demo" with only the batch_demo.info.yml file defined and enable it
3) Add this update hook to the batch_demo.install file:


function batch_demo_update_8002(&$sandbox) {
  if (!isset($sandbox['total'])) {
    $sandbox['total'] = 3;
    $sandbox['current'] = 0;
  }

  $sandbox['current']++;
  $sandbox['#finished'] = ($sandbox['current'] / $sandbox['total']);
}

4) Put your site in maintenance mode
5) Run drush updb -y
6) Observe site is taken out of maintenance mode

Repeating the same steps above, but performing the updates via update.php in a browser, and you don't have this issue.

bkosborne’s picture

Status: Active » Closed (works as designed)

Actually I just tested on the latest version of Drush 9 and it works as expected! Further digging leads to this code in the 8.x branch: https://github.com/drush-ops/drush/blob/8.x/commands/core/drupal/update....

Looks like it was a Drush 8 bug.