1. 10 Jan, 2022 1 commit
    • Rucha Deodhar's avatar
      MDEV-23836: Assertion `! is_set() || m_can_overwrite_status' in · 81e00485
      Rucha Deodhar authored
      Diagnostics_area::set_error_status (interrupted ALTER TABLE under LOCK)
      
      Analysis: KILL_QUERY is not ignored when local memory used exceeds maximum
      session memory. Hence the query proceeds, OK is sent and we end up
      reopening tables that are marked for reopen. During this, kill status is
      eventually checked and assertion failure happens during trying to send error
      message because OK has already been sent.
      Fix: Ok is already sent so statement has already executed. It is too
      late to give error. So ignore kill.
      81e00485
  2. 09 Jan, 2022 1 commit
  3. 04 Jan, 2022 1 commit
    • Marko Mäkelä's avatar
      MDEV-27416 InnoDB hang in buf_flush_wait_flushed(), on log checkpoint · 4c3ad244
      Marko Mäkelä authored
      InnoDB could sometimes hang when triggering a log checkpoint. This is
      due to commit 7b1252c0 (MDEV-24278),
      which introduced an untimed wait to buf_flush_page_cleaner().
      
      The hang was noticed by occasional failures of IMPORT TABLESPACE tests,
      such as innodb.innodb-wl5522, which would (unnecessarily) invoke
      log_make_checkpoint() from row_import_cleanup().
      
      The reason of the hang was that buf_flush_page_cleaner() would enter
      untimed sleep despite buf_flush_sync_lsn being set. The exact failure
      scenario is unclear, because buf_flush_sync_lsn should actually be
      protected by buf_pool.flush_list_mutex. We prevent the hang by
      invoking buf_pool.page_cleaner_set_idle(false) whenever we are
      setting buf_flush_sync_lsn and signaling buf_pool.do_flush_list.
      
      The bulk of these changes was originally developed as a preparation
      for MDEV-26827, to invoke buf_flush_list() from fewer threads,
      and tested on 10.6 by Matthias Leich.
      
      This fix was tested by running 100 repetitions of 100 concurrent instances
      of the test innodb.innodb-wl5522 on a RelWithDebInfo build, using ext4fs
      and innodb_flush_method=O_DIRECT on a SATA SSD with 4096-byte block size.
      During the test, the call to log_make_checkpoint() in row_import_cleanup()
      was present.
      
      buf_flush_list(): Make static.
      
      buf_flush_wait(): Wait for buf_pool.get_oldest_modification()
      to reach a target, by work done in the buf_flush_page_cleaner.
      If buf_flush_sync_lsn is going to be set, we will invoke
      buf_pool.page_cleaner_set_idle(false).
      
      buf_flush_ahead(): If buf_flush_sync_lsn or buf_flush_async_lsn
      is going to be set and the page cleaner woken up, we will invoke
      buf_pool.page_cleaner_set_idle(false).
      
      buf_flush_wait_flushed(): Invoke buf_flush_wait().
      
      buf_flush_sync(): Invoke recv_sys.apply() at the start in case
      crash recovery is active. Invoke buf_flush_wait().
      
      buf_flush_sync_batch(): A lower-level variant of buf_flush_sync()
      that is only called by recv_sys_t::apply().
      
      buf_flush_sync_for_checkpoint(): Do not trigger log apply
      or checkpoint during recovery.
      
      buf_dblwr_t::create(): Only initiate a buffer pool flush, not
      a checkpoint.
      
      row_import_cleanup(): Do not unnecessarily invoke log_make_checkpoint().
      Invoking buf_flush_list_space() before starting to generate redo log
      for the imported tablespace should suffice.
      
      srv_prepare_to_delete_redo_log_file():
      Set recv_sys.recovery_on in order to prevent
      buf_flush_sync_for_checkpoint() from initiating a checkpoint
      while the log is inaccessible. Remove a wait loop that is already
      part of buf_flush_sync().
      Do not invoke fil_names_clear() if the log is being upgraded,
      because the FILE_MODIFY record is specific to the latest format.
      
      create_log_file(): Clear recv_sys.recovery_on only after calling
      log_make_checkpoint(), to prevent buf_flush_page_cleaner from
      invoking a checkpoint.
      
      innodb_shutdown(): Simplify the logic in mariadb-backup --prepare.
      
      os_aio_wait_until_no_pending_writes(): Update the function comment.
      Apart from row_quiesce_table_start() during FLUSH TABLES...FOR EXPORT,
      this is being called by buf_flush_list_space(), which is invoked
      by ALTER TABLE...IMPORT TABLESPACE as well as some encryption operations.
      4c3ad244
  4. 03 Jan, 2022 4 commits
  5. 28 Dec, 2021 1 commit
  6. 27 Dec, 2021 2 commits
  7. 26 Dec, 2021 1 commit
  8. 25 Dec, 2021 1 commit
  9. 24 Dec, 2021 1 commit
  10. 23 Dec, 2021 6 commits
    • Julius Goryavsky's avatar
      MDEV-24097: galera[_3nodes] suite tests in MTR sporadically fails · b5cbe506
      Julius Goryavsky authored
      This is the first part of the fixes for MDEV-24097. This commit
      contains the fixes for instability when testing Galera and when
      restarting nodes quickly:
      
      1) Protection against a "stuck" old SST process during the execution
         of the new SST (after restarting the node) is now implemented for
         mariabackup / xtrabackup, which should help to avoid almost all
         conflicts due to the use of the same ports - both during testing
         with mtr, so and when restarting nodes quickly in a production
         environment.
      2) Added more protection to scripts against unexpected return of
         the rc != 0 (in the commands for deleting temporary files, etc).
      3) Added protection against unexpected crashes during binlog transfer
         (in SST scripts for rsync).
      4) Spaces and some special characters in binlog filenames shouldn't
         be a problem now (at the script level).
      5) Daemon process termination tracking has been made more robust
         against crashes due to unexpected termination of the previous SST
         process while new scripts are running.
      6) Reading ssl encryption parameters has been moved from specific
         SST scripts to a common wsrep_sst_common.sh script, which allows
         unified error handling, unified diagnostics and simplifies script
         revisions in the future.
      7) Improved diagnostics of errors related to the use of openssl.
      8) Corrections have been made for xtrabackup-v2 (both in tests and in
         the script code) that restore the work of xtrabackup with updated
         versions of innodb.
      9) Fixed some tests for galera_3nodes, although the complete solution
         for the problem of starting three nodes at the same time on fast
         machines will be done in a separate commit.
      
      No additional tests are required as this commit fixes problems with
      existing tests.
      b5cbe506
    • Julius Goryavsky's avatar
      Merge branch 10.2 into 10.3 · 3376668c
      Julius Goryavsky authored
      3376668c
    • Sergei Petrunia's avatar
      Fix typos in optimizer trace output · 4b020bfd
      Sergei Petrunia authored
      4b020bfd
    • Sergei Petrunia's avatar
      MDEV-27238: Assertion `got_name == named_item_expected()' failed in Json_writer · 397f5cf7
      Sergei Petrunia authored
      make_join_select() calls const_cond->val_int(). There are edge cases
      where const_cond may have a not-yet optimized subquery.
      
      (The subquery will have used_tables() covered by join->const_tables. It
      will still have const_item()==false, so other parts of the optimizer
      will not try to evaluate it.  We should probably mark such subqueries
      as constant but that is outside the scope of this MDEV)
      397f5cf7
    • Leandro Pacheco's avatar
      result of wsrep logic in queue_for_group_commit was being ignored · 0165a063
      Leandro Pacheco authored
      This could cause out of order wsrep checkpoints due wsrep specific leader
      code not being executed in `MYSQL_BIN_LOG::write_transaction_to_binlog_events`.
      Move original result assignment to before wsrep logic to prevent that.
      Reviewed-by: default avatarJan Lindström <jan.lindstrom@mariadb.com>
      0165a063
    • Monty's avatar
      Only apply wsrep_trx_fragment_size to InnoDB tables · ca2ea4ff
      Monty authored
      MDEV-22617 Galera node crashes when trying to log to slow_log table in
      streaming replication mode
      
      Other things:
      - Changed name of wsrep_after_row(two arguments) to
        wsrep_after_row_internal(one argument) to not depended on the
        function signature with unused arguments.
      Reviewed-by: default avatarJan Lindström <jan.lindstrom@mariadb.com>
      	     Added test case
      ca2ea4ff
  11. 22 Dec, 2021 4 commits
    • Brandon Nesterenko's avatar
      MDEV-26919: binlog.binlog_truncate_active_log fails in bb with valgrind,... · be20b3b0
      Brandon Nesterenko authored
      MDEV-26919: binlog.binlog_truncate_active_log fails in bb with valgrind, Conditional jump or move depends on uninitialised value
      
      Problem:
      ========
      When writing an XA based event to the binary log, an assert was
      always referencing thd->lex->xa_opt. This variable, however, is
      only set when using XA START, XA END, and XA COMMIT. When an
      XA PREPARE statement is being processed, it is not guaranteed that
      the xa_opt variable will be set (e.g. if existing within a stored
      procedure). This caused valgrind to complain about accessing an
      uninitialized variable.
      
      Solution:
      ========
      Before referencing xa_opt, ensure the context is valid such that
      it is set.
      
      Reviewed By:
      ============
      Andrei Elkin <andrei.elkin@mariadb.com>
      be20b3b0
    • Daniel Black's avatar
      MDEV-23175: my_timer_milliseconds clock_gettime for multiple platfomrs · 4eec6b99
      Daniel Black authored
      Small postfix to MDEV-23175 to ensure faster option on FreeBSD
      and compatibility to Solaris that isn't high resolution.
      
      ftime is left as a backup in case an implementation doesn't
      contain any of these clocks.
      
      FreeBSD
          $ ./unittest/mysys/my_rdtsc-t
          1..11
          # ----- Routine ---------------
          # myt.cycles.routine          :             5
          # myt.nanoseconds.routine     :            11
          # myt.microseconds.routine    :            13
          # myt.milliseconds.routine    :            11
          # myt.ticks.routine           :            17
          # ----- Frequency -------------
          # myt.cycles.frequency        :    3610295566
          # myt.nanoseconds.frequency   :    1000000000
          # myt.microseconds.frequency  :       1000000
          # myt.milliseconds.frequency  :           899
          # myt.ticks.frequency         :           136
          # ----- Resolution ------------
          # myt.cycles.resolution       :             1
          # myt.nanoseconds.resolution  :             1
          # myt.microseconds.resolution :             1
          # myt.milliseconds.resolution :             7
          # myt.ticks.resolution        :             1
          # ----- Overhead --------------
          # myt.cycles.overhead         :            26
          # myt.nanoseconds.overhead    :         19140
          # myt.microseconds.overhead   :         19036
          # myt.milliseconds.overhead   :           578
          # myt.ticks.overhead          :         21544
          ok 1 - my_timer_init() did not crash
          ok 2 - The cycle timer is strictly increasing
          ok 3 - The cycle timer is implemented
          ok 4 - The nanosecond timer is increasing
          ok 5 - The nanosecond timer is implemented
          ok 6 - The microsecond timer is increasing
          ok 7 - The microsecond timer is implemented
          ok 8 - The millisecond timer is increasing
          ok 9 - The millisecond timer is implemented
          ok 10 - The tick timer is increasing
          ok 11 - The tick timer is implemented
      4eec6b99
    • Daniel Black's avatar
      MDEV-23175: my_timer_milliseconds clock_gettime for multiple platfomrs · 12087d67
      Daniel Black authored
      Small postfix to MDEV-23175 to ensure faster option on FreeBSD
      and compatibility to Solaris that isn't high resolution.
      
      ftime is left as a backup in case an implementation doesn't
      contain any of these clocks.
      
      FreeBSD
          $ ./unittest/mysys/my_rdtsc-t
          1..11
          # ----- Routine ---------------
          # myt.cycles.routine          :             5
          # myt.nanoseconds.routine     :            11
          # myt.microseconds.routine    :            13
          # myt.milliseconds.routine    :            11
          # myt.ticks.routine           :            17
          # ----- Frequency -------------
          # myt.cycles.frequency        :    3610295566
          # myt.nanoseconds.frequency   :    1000000000
          # myt.microseconds.frequency  :       1000000
          # myt.milliseconds.frequency  :           899
          # myt.ticks.frequency         :           136
          # ----- Resolution ------------
          # myt.cycles.resolution       :             1
          # myt.nanoseconds.resolution  :             1
          # myt.microseconds.resolution :             1
          # myt.milliseconds.resolution :             7
          # myt.ticks.resolution        :             1
          # ----- Overhead --------------
          # myt.cycles.overhead         :            26
          # myt.nanoseconds.overhead    :         19140
          # myt.microseconds.overhead   :         19036
          # myt.milliseconds.overhead   :           578
          # myt.ticks.overhead          :         21544
          ok 1 - my_timer_init() did not crash
          ok 2 - The cycle timer is strictly increasing
          ok 3 - The cycle timer is implemented
          ok 4 - The nanosecond timer is increasing
          ok 5 - The nanosecond timer is implemented
          ok 6 - The microsecond timer is increasing
          ok 7 - The microsecond timer is implemented
          ok 8 - The millisecond timer is increasing
          ok 9 - The millisecond timer is implemented
          ok 10 - The tick timer is increasing
          ok 11 - The tick timer is implemented
      12087d67
    • Alexander Barkov's avatar
      MDEV-27195 SIGSEGV in Table_scope_and_contents_source_st::vers_check_system_fields · a5ef74e7
      Alexander Barkov authored
      The old code erroneously used default_charset_info to compare field names.
      default_charset_info can point to any arbitrary collation,
      including ucs2*, utf16*, utf32*, including those that do not
      support strcasecmp().
      
      my_charset_utf8mb4_unicode_ci, which is used in this scenario:
      
      CREATE TABLE t1 ENGINE=InnoDB WITH SYSTEM VERSIONING AS SELECT 0;
      
      does not support strcasecmp().
      
      Fixing the code to use Lex_ident::streq(), which uses
      system_charset_info instead of default_charset_info.
      a5ef74e7
  12. 21 Dec, 2021 3 commits
    • Alexander Barkov's avatar
      MDEV-27307 main.ctype_utf8mb4_uca_allkeys tests fail with Valgrind/MSAN · 6487b8e3
      Alexander Barkov authored
      In case when filesort does not use addon field packing (because of
      too small potential savings) and uses fixed width addon fields instead,
      the field->pack() call can store less bytes when the field maximum
      possible field length, e.g. in case of VARCHAR().
      The memory between the packed length and addonf->length (the maximum length)
      stayed uninitialized, which was reported by Valgrind/MSAN.
      
      The problem was introduced by f52bf920 in 10.5,
      which removed the tail initialization (probably unintentionally).
      
      Restoring the bzero() in the fixed length branch,
      so in case when pack() stores less bytes than addonf->length says,
      the trailing bytes gets initialized.
      
      Note, before f52bf920, the bzero()
      was under HAVE_valgrind conditional compilation. Now it's being added
      unconditionally:
      - MSAN also reported the problem, so it's not only Valgrind specific.
      - As Serg proposed, conditional initialization is bad - it can have
        potentional security problems as the non-initialized memory fragments
        can store various pieces of essential information, e.g. passwords.
      6487b8e3
    • sjaakola's avatar
      MDEV-27297 wsrep error log messages drop last character · 61a66d81
      sjaakola authored
      vsnprintf takes the space need for trailing '\0' in consideration, and copies only n-1 characters to destination buffer.
      With the old code, only sizeof(buf)-2 characters were copied, this caused that last character of message could be lost.
      Reviewed-by: default avatarJan Lindström <jan.lindstrom@mariadb.com>
      61a66d81
    • Marko Mäkelä's avatar
      MDEV-27332 SIGSEGV in fetch_data_into_cache() · 3b33593f
      Marko Mäkelä authored
      Since commit fb335b48 we may have
      a null pointer in purge_sys.query when fetch_data_into_cache() is
      invoked and innodb_force_recovery>4. This is because the call to
      purge_sys.create() would be skipped.
      
      fetch_data_into_cache(): Load the purge_sys pseudo transaction pointer
      to a local variable (null pointer if purge_sys is not initialized).
      3b33593f
  13. 20 Dec, 2021 2 commits
  14. 17 Dec, 2021 3 commits
  15. 16 Dec, 2021 3 commits
    • Aleksey Midenkov's avatar
      MDEV-27244 Table corruption upon adding serial data type · 3fd80d08
      Aleksey Midenkov authored
      MDEV-25803 excluded some cases from key sort upon alter table. That
      particularly depends on ALTER_ADD_INDEX flag. Creating a column of
      SERIAL data type missed that flag. Though equivalent operation
      
        alter table t1 add x bigint unsigned not null auto_increment unique;
      
      has ALTER_ADD_INDEX flag.
      3fd80d08
    • Dmitry Shulga's avatar
      MDEV-23182: Server crashes in Item::fix_fields_if_needed /... · a65d01a4
      Dmitry Shulga authored
      MDEV-23182: Server crashes in Item::fix_fields_if_needed / table_value_constr::prepare upon 2nd execution of PS
      
      Repeating execution of a query containing the clause IN with string literals
      in environment where the server variable in_predicate_conversion_threshold
      is set results in server abnormal termination in case the query is run
      as a Prepared Statement and conversion of charsets for string values in the
      query are required.
      
      The reason for server abnormal termination is that instances of the class
      Item_string created on transforming the IN clause into subquery were created
      on runtime memory root that is deallocated on finishing execution of Prepared
      statement. On the other hand, references to Items placed on deallocated memory
      root still exist in objects of the class table_value_constr. Subsequent running
      of the same prepared statement leads to dereferencing of pointers to already
      deallocated memory that could lead to undefined behaviour.
      
      To fix the issue the values being pushed into a values list for TVC are created
      by cloning their original items. This way the cloned items are allocate on
      the PS memroot and as consequences no dangling pointer does more exist.
      a65d01a4
    • Dmitry Shulga's avatar
      MDEV-21866: Assertion `!result' failed in convert_const_to_int upon 2nd execution of PS · fff8ac2e
      Dmitry Shulga authored
      Consider the following use case:
      MariaDB [test]> CREATE TABLE t1 (field1 BIGINT DEFAULT -1);
      MariaDB [test]> CREATE VIEW v1 AS SELECT DISTINCT field1 FROM t1;
      
      Repeated execution of the following query as a Prepared Statement
      
      MariaDB [test]> PREPARE stmt FROM 'SELECT * FROM v1 WHERE field1 <=> NULL';
      MariaDB [test]> EXECUTE stmt;
      
      results in a crash for a server built with DEBUG.
      
      MariaDB [test]> EXECUTE stmt;
      ERROR 2013 (HY000): Lost connection to MySQL server during query
      
      Assertion failed: (!result), function convert_const_to_int, file item_cmpfunc.cc, line 476.
      Abort trap: 6 (core dumped)
      
      The crash inside the function convert_const_to_int() happens by the reason
      that the value -1 is stored in an instance of the class Field_longlong
      on restoring its original value in the statement
        result= field->store(orig_field_val, TRUE);
      that leads to assigning the value 1 to the variable 'result' with subsequent
      crash in the DBUG_ASSERT statement following it
        DBUG_ASSERT(!result);
      
      The main matter here is why this assertion failure happens on the second
      execution of the prepared statement and doens't on the first one.
      On first handling of the statement
        'EXECUTE stmt;'
      a temporary table is created for serving the query involving the view 'v1'.
      The table is created by the function create_tmp_table() in the following
      calls trace: (trace #1)
        JOIN::prepare (at sql_select.cc:725)
          st_select_lex::handle_derived
            LEX::handle_list_of_derived
              TABLE_LIST::handle_derived
                mysql_handle_single_derived
                  mysql_derived_prepare
                    select_union::create_result_table
                      create_tmp_table
      
      Note, that the data member TABLE::status of a TABLE instance returned by the
      function create_tmp_table() has the value 0.
      
      Later the function setup_table_map() is called on the TABLE instance just
      created for the sake of the temporary table (calls trace #2 is below):
        JOIN::prepare (at sql_select.cc:737)
          setup_tables_and_check_access
            setup_tables
              setup_table_map
      where the data member TABLE::status is set to the value STATUS_NO_RECORD.
      
      After that when execution of the method JOIN::prepare reaches calling of
      the function setup_without_group() the following calls trace is invoked
        JOIN::prepare
          setup_without_group
            setup_conds
              Item_func::fix_fields
                Item_func_equal::fix_length_and_dec
                  Item_bool_rowready_func2::fix_length_and_dec
                    Item_func::setup_args_and_comparator
                      Item_func::convert_const_compared_to_int_field
                        convert_const_to_int
      
      There is the following code snippet in the function convert_const_to_int()
      at the line item_cmpfunc.cc:448
          bool save_field_value= (field_item->const_item() ||
                                  !(field->table->status & STATUS_NO_RECORD));
      Since field->table->status has bits STATUS_NO_RECORD set the variable
      save_field_value is false and therefore neither the method
      Field_longlong::val_int() nor the method Field_longlong::store is called
      on the Field instance that has the numeric value -1.
      That is the reason why first execution of the Prepared Statement for the query
        'SELECT * FROM v1 WHERE field1 <=> NULL'
      is successful.
      
      On second running of the statement 'EXECUTE stmt' a new temporary tables
      is also created by running the calls trace #1 but the trace #2 is not executed
      by the reason that data member SELECT_LEX::first_cond_optimization has been set
      to false on first execution of the prepared statemet (in the method
      JOIN::optimize_inner()). As a consequence, the data member TABLE::status for
      a temporary table just created doesn't have the flags STATUS_NO_RECORD set and
      therefore on re-execution of the prepared statement the methods
      Field_longlong::val_int() and Field_longlong::store() are called for the field
      having the value -1 and the DBUG_ASSERT(!result) is fired.
      
      To fix the issue the data member TABLE::status has to be assigned the value
      STATUS_NO_RECORD in every place where the macros empty_record() is called
      to emptify a record for just instantiated TABLE object created on behalf
      the new temporary table.
      fff8ac2e
  16. 15 Dec, 2021 6 commits
    • Daniel Black's avatar
      MDEV-24788: mariadbd --help Can't lock aria control file · 2776635c
      Daniel Black authored
      ... '/var/lib/mysql/aria_log_control' for exclusive use, error: 11
      
      As such don't lock under aria_readonly (which is set by opt_help in the handler
      initialization.
      
      Fixes: 8eba777c
      2776635c
    • Monty's avatar
      Fixed some tests that failes when built with valgrind · 20f22dfa
      Monty authored
      Example build: ./BUILD/compile-pentium64-valgrind-max
      
      Fixes:
      - sp-no-valgrind failed if binary was built for valgrind as in this case
        mem_root is allocated in very small hunks which the test cannot handle.
        Fixed by testing of valgrind build
      - truncate_notembedded failed in reap because of more memory used.
        Fixed by allowing reap to fail too
      20f22dfa
    • Sergei Petrunia's avatar
      MDEV-27270: Wrong query plan with Range Checked for Each Record and ORDER BY ... LIMIT · 136bcfdf
      Sergei Petrunia authored
      Followup to fix for MDEV-25858: When test_if_skip_sort_order() decides
      to use an index to satisfy ORDER BY ... LIMIT clause, it should
      disable "Range Checked for Each Record" optimization.
      
      Do this in all cases.
      136bcfdf
    • Monty's avatar
      Add --optimizer_trace option to mysqltest · 607b14c4
      Monty authored
      This enables optimizer_trace output for the next SQL command.
      Identical as if one would have done:
      - Store value of @@optimizer_trace
      - Set @optimizer_trace="enabled=on"
      - Run query
      - SELECT * from OPTIMIZER_TRACE
      - Restore value of @@optimizer_trace
      
      This is a great time saver when one wants to quickly check the optimizer
      trace for a query in a mtr test.
      607b14c4
    • Jan Lindström's avatar
      Disable following tests from galera_3nodes suite · f1ca949f
      Jan Lindström authored
      * galera_pc_bootstrap
      * galera_ipv6_mariabackup
      * galera_ipv6_mariabackup_section
      * galera_ipv6_rsync
      * galera_ipv6_rsync_section
      * galera_ssl_reload
      * galera_toi_vote
      * galera_wsrep_schema_init
      
      because MTR sporadaically fails: Failed to start mysqld or mysql_shutdown failed
      f1ca949f
    • Monty's avatar
      MDEV-18187 Aria engine: Redo phase failed with "error 192 when executing... · 3691cc15
      Monty authored
      MDEV-18187 Aria engine: Redo phase failed with "error 192 when executing record redo_index_new_page" upon startup on a restored datadir
      
      The issue is that when recovery is about to create a new data or index
      page it check if the page already exits.
      If the page does not exists (file is too short) or contains wrong checksum,
      then the recovery code will recreate the page.
      The bug was that the code that checked if the page existed didn't take
      into account encrypted pages.
      
      Fixed by adding a check if page could not be encrypted solved the issue.
      I also added some code to silence decryption errors for new pages.
      
      Test case and some inspiration for how to solve this come from
      the pull request by alexandr.miloslavsky
      3691cc15