Does release_handler:rollback/1 guarantee consistency after a failed OTP upgrade?
0 reputation · 25 Jul 2020, 00:44 UTC
0 reputation · 25 Jul 2020, 00:44 UTC
Determine whether release_handler:rollback/1 can safely return a running Erlang node to the previous release after an upgrade fails partway through activation.
Assuming a standard OTP release with release_handler and relup support, the upgrade may already have loaded new modules and migrated some processes while other nodes or processes still run the old code. Documentation indicates rollback is manual and requires the prior release to remain available, but it does not specify what happens to process state already transformed by code_change/3, or to shared resources such as ETS tables and files rewritten by the new release.
Specific questions:
release_handler:rollback/1 revert every process to the old code version, or only processes that have not yet completed the code change?34775 reputation · 25 Jul 2020, 04:42 UTC
No. release_handler:rollback/1 does not guarantee that a running Erlang node is in a semantically consistent state after a partially failed upgrade. It only updates the release bookkeeping and executes any downgrade sections defined in the relup script for the previous release.
rollback/1 means the release handler marked the old release as current and removed the failed release from the list of active releases. It does not automatically revert process heaps, dictionaries, ETS tables, files, or any external side effects that the new code may have already performed.code_change/3 and migrated state, that state remains unchanged unless the relup downgrade section explicitly calls the corresponding downgrade callback. Processes that never ran code_change/3 are simply reloaded with the old module code.code_change/3 when the rollback starts; quiesce the system if necessary.relup file for the previous release.relup file for a downgrade section that matches the previous release.code_change/3 calls.release_handler:rollback(PrevRelease) where PrevRelease is the directory name of the previous release.release_handler:which_releases() should list the old release as current and the failed one as inactive.code:which(Module) should point to files in the old release directory.Did the new release write to any ETS tables, files, or external resources before it failed? If yes, plan a manual state repair in addition to the code rollback; if no, code‑level rollback may be sufficient, but always verify process state.
Use comments to ask for clarification. Post a solution as an answer.
5,540 reputation · 25 Jul 2020, 09:21 UTC
Calling release_handler:rollback/1 makes the previous release the current one for future code loads, but it does not force processes that have already executed their code_change/3 callbacks to revert to the old module version or undo any state they transformed. Those processes continue running the new code until they are restarted (or explicitly downgraded via sys:suspend/code_change). Consequently, any mutable resources—such as ETS tables, file writes, or external database updates—performed by the new release before the failure remain unchanged; the application must provide its own compensation logic if those changes are not idempotent. This behavior is consistent across OTP 24 and later, assuming the old release is still present on disk and the node has not been restarted after the failed upgrade.