Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix failing pragma journal_mode=off execution and subsequent crash #1567

Closed

Conversation

infinitewarp
Copy link

@infinitewarp infinitewarp commented Feb 27, 2023

I recently encountered an issue that would sometimes cause coverage to crash despite no changes to the code it was testing/running against. Apparently some builds of Python+SQLite refuse to apply pragma journal_mode=off (they allow it to "execute" but actually silently ignore it), and that can results in short-lived *-journal files appearing on the filesystem since the default pragma journal_mode=delete is still in effect. When coverage runs in multi/parallel mode and attempts to combine results from its separate files, sometimes (presumably depending on OS/filesystem sync timing) some of the *-journal files may still briefly exist, and this can cause coverage to crash.

Real-world example of coverage crashing at the end of testing a project I was recently working on:

INTERNALERROR> Traceback (most recent call last):
INTERNALERROR>   File "/Users/brasmith/Library/Caches/pypoetry/virtualenvs/quipucords-A54Z8Zh8-py3.9/lib/python3.9/site-packages/_pytest/main.py", line 270, in wrap_session
INTERNALERROR>     session.exitstatus = doit(config, session) or 0
INTERNALERROR>   File "/Users/brasmith/Library/Caches/pypoetry/virtualenvs/quipucords-A54Z8Zh8-py3.9/lib/python3.9/site-packages/_pytest/main.py", line 324, in _main
INTERNALERROR>     config.hook.pytest_runtestloop(session=session)
INTERNALERROR>   File "/Users/brasmith/Library/Caches/pypoetry/virtualenvs/quipucords-A54Z8Zh8-py3.9/lib/python3.9/site-packages/pluggy/_hooks.py", line 265, in __call__
INTERNALERROR>     return self._hookexec(self.name, self.get_hookimpls(), kwargs, firstresult)
INTERNALERROR>   File "/Users/brasmith/Library/Caches/pypoetry/virtualenvs/quipucords-A54Z8Zh8-py3.9/lib/python3.9/site-packages/pluggy/_manager.py", line 80, in _hookexec
INTERNALERROR>     return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
INTERNALERROR>   File "/Users/brasmith/Library/Caches/pypoetry/virtualenvs/quipucords-A54Z8Zh8-py3.9/lib/python3.9/site-packages/pluggy/_callers.py", line 55, in _multicall
INTERNALERROR>     gen.send(outcome)
INTERNALERROR>   File "/Users/brasmith/Library/Caches/pypoetry/virtualenvs/quipucords-A54Z8Zh8-py3.9/lib/python3.9/site-packages/pytest_cov/plugin.py", line 294, in pytest_runtestloop
INTERNALERROR>     self.cov_controller.finish()
INTERNALERROR>   File "/Users/brasmith/Library/Caches/pypoetry/virtualenvs/quipucords-A54Z8Zh8-py3.9/lib/python3.9/site-packages/pytest_cov/engine.py", line 44, in ensure_topdir_wrapper
INTERNALERROR>     return meth(self, *args, **kwargs)
INTERNALERROR>   File "/Users/brasmith/Library/Caches/pypoetry/virtualenvs/quipucords-A54Z8Zh8-py3.9/lib/python3.9/site-packages/pytest_cov/engine.py", line 326, in finish
INTERNALERROR>     self.cov.stop()
INTERNALERROR>   File "/Users/brasmith/Library/Caches/pypoetry/virtualenvs/quipucords-A54Z8Zh8-py3.9/lib/python3.9/site-packages/coverage/control.py", line 790, in combine
INTERNALERROR>     combine_parallel_data(
INTERNALERROR>   File "/Users/brasmith/Library/Caches/pypoetry/virtualenvs/quipucords-A54Z8Zh8-py3.9/lib/python3.9/site-packages/coverage/data.py", line 153, in combine_parallel_data
INTERNALERROR>     with open(f, "rb") as fobj:
INTERNALERROR> FileNotFoundError: [Errno 2] No such file or directory: '/Users/brasmith/projects/quipucords/.coverage.brasmith-shadowbook.lan.80545.469681-journal'

It was difficult to isolate a reproducible example with coverage itself running against another project, but I was able to at least verify independently that, yes, some builds of Python+SQLite refuse or ignore pragma journal_mode=off. See: https://github.com/infinitewarp/test-python-sqlite-journal_mode. The TLDR is that the default macOS 13.2.1 build and pyenv-installed builds fail, but homebrew-installed builds and Linux builds inside various Docker images work as expected.

Since I would like coverage to work reliably in my pyenv-installed environments, I'm proposing two changes with this PR, but I'm happy to drop one in favor of the other or to consider alternate implementations:

  1. Check if the pragma journal_mode=off actually succeeded. If it didn't, execute pragma journal_mode=memory so the filesystem should never be dirtied with *-journal files. Based on my local testing and understanding of the SQLite documentation, the memory mode should still be available even when off is not. This might impact memory use or performance, but I suspect the effect would be negligible and a worthwhile tradeoff for stability.
  2. Wrap the file-reading context in combine_parallel_data with a try, and handle the FileNotFoundError exception. This would help in the case where the -journal file exists when combinable_files is called but has been deleted by the time combine_parallel_data tries to read it. Weird as it sounds, that does appear to happen sometimes. This handling shouldn't be necessary if 1 succeeded in setting pragma journal_mode=memory, and I considered dropping this part from the PR, but I thought it might not hurt to have some extra checking there.

Please let me know what you think. 🙂 This problem took a while to figure out since the behavior was so inconsistent between runs and environments, and I'm happy to revise this PR or consider alternate ideas if you have them. I feel like neither 1 nor 2 is ideal, but given the fact that some Python+SQLite builds are misbehaving, I couldn't think of a better solution.

@infinitewarp infinitewarp force-pushed the improve-sqlite-journal branch 2 times, most recently from c12ad54 to 06d121d Compare February 27, 2023 17:55
@nedbat
Copy link
Owner

nedbat commented Mar 16, 2023

Another option for #2 is to ignore '*-journal' files, though that also feels a bit janky. Can you show the output of coverage debug sys on the system that doesn't disable journaling? I'm curious if there's visible difference in the sqlite3_* settings there.

coverage/data.py Outdated Show resolved Hide resolved
coverage/sqldata.py Outdated Show resolved Hide resolved
@nedbat
Copy link
Owner

nedbat commented Mar 16, 2023

I don't understand when SQLite accepts the setting change and when it doesn't.

I sabotaged the test suite like this:

diff --git a/coverage/sqldata.py b/coverage/sqldata.py
index 3e47b4d8..5c4690e6 100644
--- a/coverage/sqldata.py
+++ b/coverage/sqldata.py
@@ -1132,7 +1132,10 @@ def _connect(self) -> None:
         # This pragma makes writing faster. It disables rollbacks, but we never need them.
         # PyPy needs the .close() calls here, or sqlite gets twisted up:
         # https://bitbucket.org/pypy/pypy/issues/2872/default-isolation-mode-is-different-on
+        jmode0 = self.execute_one("pragma journal_mode")
         self.execute_void("pragma journal_mode=off")
+        jmode1 = self.execute_one("pragma journal_mode")
+        raise Exception(f"{sys.version.split()[0]}: {jmode0!r} -> {jmode1!r}")
         if self.execute_one("pragma journal_mode") != "off":
             # Some instances of Sqlite refuse to disable journal mode.
             # Switching to memory mode prevents journal files from being written,

Then ran it locally on my Mac, and also in GitHub Actions. These were the results:

Local mac:
3.7.15: ('delete',) -> ('off',)
3.8.15: ('delete',) -> ('off',)
3.9.15: ('delete',) -> ('off',)
3.10.10: ('delete',) -> ('delete',)
3.11.2: ('delete',) -> ('delete',)
3.12.0a6: ('delete',) -> ('delete',)
pypy 3.7.13: ('delete',) -> ('delete',)
pypy 3.8.16: ('delete',) -> ('delete',)
pypy 3.9.16: ('delete',) -> ('delete',)

CI ubuntu:
3.7.16: ('delete',) -> ('off',)
3.8.16: ('delete',) -> ('off',)
3.9.16: ('delete',) -> ('off',)
3.10.10: ('delete',) -> ('off',)
3.11.2: ('delete',) -> ('off',)
pypy 3.7.13: ('delete',) -> ('off',)
pypy 3.9.16: ('delete',) -> ('off',)

CI mac:
3.7.15: ('delete',) -> ('off',)
3.8.16: ('delete',) -> ('off',)
3.9.16: ('delete',) -> ('off',)
3.10.10: ('delete',) -> ('off',)
3.11.2: ('delete',) -> ('off',)
pypy 3.7.13: ('delete',) -> ('delete',)
pypy 3.9.16: ('delete',) -> ('delete',)

CI windows:
3.7.9: ('delete',) -> ('off',)
3.8.10: ('delete',) -> ('off',)
3.9.13: ('delete',) -> ('off',)
3.10.10: ('delete',) -> ('off',)
3.11.2: ('delete',) -> ('off',)
pypy 3.7.13: ('delete',) -> ('off',)

Looking at the settings between the local versions that changed to "off" and those that kept "delete", they are the same:

         sqlite3_sqlite_version: 3.39.5
             sqlite3_temp_store: 0
        sqlite3_compile_options: ATOMIC_INTRINSICS=1, BUG_COMPATIBLE_20160819, CCCRYPT256,
                                 COMPILER=clang-14.0.0, DEFAULT_AUTOVACUUM, DEFAULT_CACHE_SIZE=2000,
                                 DEFAULT_CKPTFULLFSYNC, DEFAULT_FILE_FORMAT=4,
                                 DEFAULT_JOURNAL_SIZE_LIMIT=32768, DEFAULT_LOOKASIDE=1200,102,
                                 DEFAULT_MEMSTATUS=0, DEFAULT_MMAP_SIZE=0, DEFAULT_PAGE_SIZE=4096,
                                 DEFAULT_PCACHE_INITSZ=20, DEFAULT_RECURSIVE_TRIGGERS,
                                 DEFAULT_SECTOR_SIZE=4096, DEFAULT_SYNCHRONOUS=2,
                                 DEFAULT_WAL_AUTOCHECKPOINT=1000, DEFAULT_WAL_SYNCHRONOUS=1,
                                 DEFAULT_WORKER_THREADS=0, ENABLE_API_ARMOR, ENABLE_BYTECODE_VTAB,
                                 ENABLE_COLUMN_METADATA, ENABLE_DBSTAT_VTAB, ENABLE_FTS3,
                                 ENABLE_FTS3_PARENTHESIS, ENABLE_FTS3_TOKENIZER, ENABLE_FTS4, ENABLE_FTS5,
                                 ENABLE_LOCKING_STYLE=1, ENABLE_NORMALIZE, ENABLE_PREUPDATE_HOOK,
                                 ENABLE_RTREE, ENABLE_SESSION, ENABLE_SNAPSHOT, ENABLE_SQLLOG,
                                 ENABLE_STMT_SCANSTATUS, ENABLE_UNKNOWN_SQL_FUNCTION,
                                 ENABLE_UPDATE_DELETE_LIMIT, HAS_CODEC_RESTRICTED, HAVE_ISNAN,
                                 MALLOC_SOFT_LIMIT=1024, MAX_ATTACHED=10, MAX_COLUMN=2000,
                                 MAX_COMPOUND_SELECT=500, MAX_DEFAULT_PAGE_SIZE=8192, MAX_EXPR_DEPTH=1000,
                                 MAX_FUNCTION_ARG=127, MAX_LENGTH=2147483645, MAX_LIKE_PATTERN_LENGTH=50000,
                                 MAX_MMAP_SIZE=1073741824, MAX_PAGE_COUNT=1073741823, MAX_PAGE_SIZE=65536,
                                 MAX_SQL_LENGTH=1000000000, MAX_TRIGGER_DEPTH=1000,
                                 MAX_VARIABLE_NUMBER=500000, MAX_VDBE_OP=250000000, MAX_WORKER_THREADS=8,
                                 MUTEX_UNFAIR, OMIT_AUTORESET, OMIT_LOAD_EXTENSION, STMTJRNL_SPILL=131072,
                                 SYSTEM_MALLOC, TEMP_STORE=1, THREADSAFE=2, USE_URI

@infinitewarp
Copy link
Author

Another option for #2 is to ignore '*-journal' files, though that also feels a bit janky.

Yeah, my original local quick-and-dirty fix was exactly that. I added a simple condition in combinable_files, something like this:

diff --git a/coverage/data.py b/coverage/data.py
index abe6b510..7ab9fdcd 100644
--- a/coverage/data.py
+++ b/coverage/data.py
@@ -76,7 +76,7 @@ def combinable_files(data_file: str, data_paths: Optional[Iterable[str]] = None)
     data_paths = data_paths or [data_dir]
     files_to_combine = []
     for p in data_paths:
-        if os.path.isfile(p):
+        if os.path.isfile(p) and not p.endswith('.journal'):
             files_to_combine.append(os.path.abspath(p))
         elif os.path.isdir(p):
             pattern = glob.escape(os.path.join(os.path.abspath(p), local)) +".*"

That may or may not be what I actually tried; I'm just recreating it from memory. In any case, this felt too crude because I think if a journal file exists, that means that its paired sqlite db file might not actually have the change committed and may be slightly out of date, which means when coverage reads its contents, it may be incorrect or invalid. That's why I pursued the heavier-handed approach of checking pragma journal_mode directly and switching entirely to memory.

Can you show the output of coverage debug sys on the system that doesn't disable journaling? I'm curious if there's visible difference in the sqlite3_* settings there.

Sure, I'll switch over to that system shortly and include the output somewhere.

@infinitewarp infinitewarp force-pushed the improve-sqlite-journal branch 2 times, most recently from 34a8df9 to 5d25343 Compare March 20, 2023 19:51
@infinitewarp
Copy link
Author

Can you show the output of coverage debug sys on the system that doesn't disable journaling?

I switched to one of my problematic pyenv-installed Python installations, created a new venv, and confirmed off was being ignored:

❯ rm -rf venv
❯ python -m venv venv
❯ source venv/bin/activate
❯ python -m pip -q install -U pip
❯ python -m pip -q install coverage==7.2.2
❯ python -m pip freeze
coverage==7.2.2
❯ cat <<EOF | python
import sqlite3
with sqlite3.connect('/tmp/foo') as con:
  con.execute('pragma journal_mode=off')
  print(con.execute("pragma journal_mode").fetchone())
EOF
('delete',)

Some general info about this Python which was originally installed using pyenv install 3.10.5 with no other args:

❯ python --version
Python 3.10.5
❯ which python
/Users/brasmith/projects/test_journal_mode/venv/bin/python
❯ pyenv which python
/Users/brasmith/.pyenv/versions/3.10.5/bin/python
❯ ls -la `which python`
lrwxr-xr-x  1 brasmith  staff  49 Mar 20 16:32 /Users/brasmith/projects/test_journal_mode/venv/bin/python -> /Users/brasmith/.pyenv/versions/3.10.5/bin/python
❯ sw_vers
ProductName:		macOS
ProductVersion:		13.2.1
BuildVersion:		22D68
❯ uname -a
Darwin brasmith-shadowbook.lan 22.3.0 Darwin Kernel Version 22.3.0: Mon Jan 30 20:42:11 PST 2023; root:xnu-8792.81.3~2/RELEASE_X86_64 x86_64

And finally coverage's debug output:

❯ coverage debug sys
-- sys -------------------------------------------------------
               coverage_version: 7.2.2
                coverage_module: /Users/brasmith/projects/test_journal_mode/venv/lib/python3.10/site-packages/coverage/__init__.py
                         tracer: -none-
                        CTracer: available
           plugins.file_tracers: -none-
            plugins.configurers: -none-
      plugins.context_switchers: -none-
              configs_attempted: .coveragerc
                                 setup.cfg
                                 tox.ini
                                 pyproject.toml
                   configs_read: -none-
                    config_file: None
                config_contents: -none-
                      data_file: -none-
                         python: 3.10.5 (main, Jun 17 2022, 16:21:05) [Clang 13.1.6 (clang-1316.0.21.2.3)]
                       platform: macOS-13.2.1-x86_64-i386-64bit
                 implementation: CPython
                     executable: /Users/brasmith/projects/test_journal_mode/venv/bin/python
                   def_encoding: utf-8
                    fs_encoding: utf-8
                            pid: 39636
                            cwd: /Users/brasmith/projects/test_journal_mode
                           path: /Users/brasmith/projects/test_journal_mode/venv/bin
                                 /Users/brasmith/.pyenv/versions/3.10.5/lib/python310.zip
                                 /Users/brasmith/.pyenv/versions/3.10.5/lib/python3.10
                                 /Users/brasmith/.pyenv/versions/3.10.5/lib/python3.10/lib-dynload
                                 /Users/brasmith/projects/test_journal_mode/venv/lib/python3.10/site-packages
                    environment: HOME = /Users/brasmith
                                 PYENV_ROOT = /Users/brasmith/.pyenv
                   command_line: /Users/brasmith/projects/test_journal_mode/venv/bin/coverage debug sys
         sqlite3_sqlite_version: 3.39.5
             sqlite3_temp_store: 0
        sqlite3_compile_options: ATOMIC_INTRINSICS=1, BUG_COMPATIBLE_20160819, CCCRYPT256,
                                 COMPILER=clang-14.0.0, DEFAULT_AUTOVACUUM, DEFAULT_CACHE_SIZE=2000,
                                 DEFAULT_CKPTFULLFSYNC, DEFAULT_FILE_FORMAT=4,
                                 DEFAULT_JOURNAL_SIZE_LIMIT=32768, DEFAULT_LOOKASIDE=1200,102,
                                 DEFAULT_MEMSTATUS=0, DEFAULT_MMAP_SIZE=0, DEFAULT_PAGE_SIZE=4096,
                                 DEFAULT_PCACHE_INITSZ=20, DEFAULT_RECURSIVE_TRIGGERS,
                                 DEFAULT_SECTOR_SIZE=4096, DEFAULT_SYNCHRONOUS=2,
                                 DEFAULT_WAL_AUTOCHECKPOINT=1000, DEFAULT_WAL_SYNCHRONOUS=1,
                                 DEFAULT_WORKER_THREADS=0, ENABLE_API_ARMOR, ENABLE_BYTECODE_VTAB,
                                 ENABLE_COLUMN_METADATA, ENABLE_DBSTAT_VTAB, ENABLE_FTS3,
                                 ENABLE_FTS3_PARENTHESIS, ENABLE_FTS3_TOKENIZER, ENABLE_FTS4, ENABLE_FTS5,
                                 ENABLE_LOCKING_STYLE=1, ENABLE_NORMALIZE, ENABLE_PREUPDATE_HOOK,
                                 ENABLE_RTREE, ENABLE_SESSION, ENABLE_SNAPSHOT, ENABLE_SQLLOG,
                                 ENABLE_STMT_SCANSTATUS, ENABLE_UNKNOWN_SQL_FUNCTION,
                                 ENABLE_UPDATE_DELETE_LIMIT, HAS_CODEC_RESTRICTED, HAVE_ISNAN,
                                 MALLOC_SOFT_LIMIT=1024, MAX_ATTACHED=10, MAX_COLUMN=2000,
                                 MAX_COMPOUND_SELECT=500, MAX_DEFAULT_PAGE_SIZE=8192, MAX_EXPR_DEPTH=1000,
                                 MAX_FUNCTION_ARG=127, MAX_LENGTH=2147483645, MAX_LIKE_PATTERN_LENGTH=50000,
                                 MAX_MMAP_SIZE=1073741824, MAX_PAGE_COUNT=1073741823, MAX_PAGE_SIZE=65536,
                                 MAX_SQL_LENGTH=1000000000, MAX_TRIGGER_DEPTH=1000,
                                 MAX_VARIABLE_NUMBER=500000, MAX_VDBE_OP=250000000, MAX_WORKER_THREADS=8,
                                 MUTEX_UNFAIR, OMIT_AUTORESET, OMIT_LOAD_EXTENSION, STMTJRNL_SPILL=131072,
                                 SYSTEM_MALLOC, TEMP_STORE=1, THREADSAFE=2, USE_URI

My homebrew-installed Python builds appears to correctly support off, and using one of them:

❯ coverage debug sys
-- sys -------------------------------------------------------
               coverage_version: 7.2.2
                coverage_module: /Users/brasmith/projects/test_journal_mode/venv-brew/lib/python3.10/site-packages/coverage/__init__.py
                         tracer: -none-
                        CTracer: available
           plugins.file_tracers: -none-
            plugins.configurers: -none-
      plugins.context_switchers: -none-
              configs_attempted: .coveragerc
                                 setup.cfg
                                 tox.ini
                                 pyproject.toml
                   configs_read: -none-
                    config_file: None
                config_contents: -none-
                      data_file: -none-
                         python: 3.10.10 (main, Feb 16 2023, 02:55:02) [Clang 14.0.0 (clang-1400.0.29.202)]
                       platform: macOS-13.2.1-x86_64-i386-64bit
                 implementation: CPython
                     executable: /Users/brasmith/projects/test_journal_mode/venv-brew/bin/python
                   def_encoding: utf-8
                    fs_encoding: utf-8
                            pid: 41318
                            cwd: /Users/brasmith/projects/test_journal_mode
                           path: /Users/brasmith/projects/test_journal_mode/venv-brew/bin
                                 /usr/local/Cellar/python@3.10/3.10.10_1/Frameworks/Python.framework/Versions/3.10/lib/python310.zip
                                 /usr/local/Cellar/python@3.10/3.10.10_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10
                                 /usr/local/Cellar/python@3.10/3.10.10_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10/lib-dynload
                                 /Users/brasmith/projects/test_journal_mode/venv-brew/lib/python3.10/site-packages
                    environment: HOME = /Users/brasmith
                                 PYENV_ROOT = /Users/brasmith/.pyenv
                   command_line: /Users/brasmith/projects/test_journal_mode/venv-brew/bin/coverage debug sys
         sqlite3_sqlite_version: 3.40.1
             sqlite3_temp_store: 0
        sqlite3_compile_options: ATOMIC_INTRINSICS=1, COMPILER=clang-14.0.0, DEFAULT_AUTOVACUUM,
                                 DEFAULT_CACHE_SIZE=-2000, DEFAULT_FILE_FORMAT=4,
                                 DEFAULT_JOURNAL_SIZE_LIMIT=-1, DEFAULT_MMAP_SIZE=0, DEFAULT_PAGE_SIZE=4096,
                                 DEFAULT_PCACHE_INITSZ=20, DEFAULT_RECURSIVE_TRIGGERS,
                                 DEFAULT_SECTOR_SIZE=4096, DEFAULT_SYNCHRONOUS=2,
                                 DEFAULT_WAL_AUTOCHECKPOINT=1000, DEFAULT_WAL_SYNCHRONOUS=2,
                                 DEFAULT_WORKER_THREADS=0, ENABLE_COLUMN_METADATA, ENABLE_FTS3,
                                 ENABLE_FTS3_PARENTHESIS, ENABLE_FTS4, ENABLE_FTS5, ENABLE_GEOPOLY,
                                 ENABLE_MATH_FUNCTIONS, ENABLE_PREUPDATE_HOOK, ENABLE_RTREE, ENABLE_SESSION,
                                 MALLOC_SOFT_LIMIT=1024, MAX_ATTACHED=10, MAX_COLUMN=2000,
                                 MAX_COMPOUND_SELECT=500, MAX_DEFAULT_PAGE_SIZE=8192, MAX_EXPR_DEPTH=1000,
                                 MAX_FUNCTION_ARG=127, MAX_LENGTH=1000000000, MAX_LIKE_PATTERN_LENGTH=50000,
                                 MAX_MMAP_SIZE=0x7fff0000, MAX_PAGE_COUNT=1073741823, MAX_PAGE_SIZE=65536,
                                 MAX_SQL_LENGTH=1000000000, MAX_TRIGGER_DEPTH=1000,
                                 MAX_VARIABLE_NUMBER=250000, MAX_VDBE_OP=250000000, MAX_WORKER_THREADS=8,
                                 MUTEX_PTHREADS, SYSTEM_MALLOC, TEMP_STORE=1, THREADSAFE=1

Diffing the output, there are several compile option differences between pyenv's and brew's:

--- /Users/brasmith/Desktop/coverage_pyenv_python.txt	2023-03-20 17:02:42
+++ /Users/brasmith/Desktop/coverage_brew_python.txt	2023-03-20 17:07:11
@@ -1,6 +1,6 @@
 -- sys -------------------------------------------------------
                coverage_version: 7.2.2
-                coverage_module: /Users/brasmith/projects/test_journal_mode/venv/lib/python3.10/site-packages/coverage/__init__.py
+                coverage_module: /Users/brasmith/projects/test_journal_mode/venv-brew/lib/python3.10/site-packages/coverage/__init__.py
                          tracer: -none-
                         CTracer: available
            plugins.file_tracers: -none-
@@ -14,44 +14,37 @@
                     config_file: None
                 config_contents: -none-
                       data_file: -none-
-                         python: 3.10.5 (main, Jun 17 2022, 16:21:05) [Clang 13.1.6 (clang-1316.0.21.2.3)]
+                         python: 3.10.10 (main, Feb 16 2023, 02:55:02) [Clang 14.0.0 (clang-1400.0.29.202)]
                        platform: macOS-13.2.1-x86_64-i386-64bit
                  implementation: CPython
-                     executable: /Users/brasmith/projects/test_journal_mode/venv/bin/python
+                     executable: /Users/brasmith/projects/test_journal_mode/venv-brew/bin/python
                    def_encoding: utf-8
                     fs_encoding: utf-8
-                            pid: 41054
+                            pid: 41353
                             cwd: /Users/brasmith/projects/test_journal_mode
-                           path: /Users/brasmith/projects/test_journal_mode/venv/bin
-                                 /Users/brasmith/.pyenv/versions/3.10.5/lib/python310.zip
-                                 /Users/brasmith/.pyenv/versions/3.10.5/lib/python3.10
-                                 /Users/brasmith/.pyenv/versions/3.10.5/lib/python3.10/lib-dynload
-                                 /Users/brasmith/projects/test_journal_mode/venv/lib/python3.10/site-packages
+                           path: /Users/brasmith/projects/test_journal_mode/venv-brew/bin
+                                 /usr/local/Cellar/python@3.10/3.10.10_1/Frameworks/Python.framework/Versions/3.10/lib/python310.zip
+                                 /usr/local/Cellar/python@3.10/3.10.10_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10
+                                 /usr/local/Cellar/python@3.10/3.10.10_1/Frameworks/Python.framework/Versions/3.10/lib/python3.10/lib-dynload
+                                 /Users/brasmith/projects/test_journal_mode/venv-brew/lib/python3.10/site-packages
                     environment: HOME = /Users/brasmith
                                  PYENV_ROOT = /Users/brasmith/.pyenv
-                   command_line: /Users/brasmith/projects/test_journal_mode/venv/bin/coverage debug sys
-         sqlite3_sqlite_version: 3.39.5
+                   command_line: /Users/brasmith/projects/test_journal_mode/venv-brew/bin/coverage debug sys
+         sqlite3_sqlite_version: 3.40.1
              sqlite3_temp_store: 0
-        sqlite3_compile_options: ATOMIC_INTRINSICS=1, BUG_COMPATIBLE_20160819, CCCRYPT256,
-                                 COMPILER=clang-14.0.0, DEFAULT_AUTOVACUUM, DEFAULT_CACHE_SIZE=2000,
-                                 DEFAULT_CKPTFULLFSYNC, DEFAULT_FILE_FORMAT=4,
-                                 DEFAULT_JOURNAL_SIZE_LIMIT=32768, DEFAULT_LOOKASIDE=1200,102,
-                                 DEFAULT_MEMSTATUS=0, DEFAULT_MMAP_SIZE=0, DEFAULT_PAGE_SIZE=4096,
+        sqlite3_compile_options: ATOMIC_INTRINSICS=1, COMPILER=clang-14.0.0, DEFAULT_AUTOVACUUM,
+                                 DEFAULT_CACHE_SIZE=-2000, DEFAULT_FILE_FORMAT=4,
+                                 DEFAULT_JOURNAL_SIZE_LIMIT=-1, DEFAULT_MMAP_SIZE=0, DEFAULT_PAGE_SIZE=4096,
                                  DEFAULT_PCACHE_INITSZ=20, DEFAULT_RECURSIVE_TRIGGERS,
                                  DEFAULT_SECTOR_SIZE=4096, DEFAULT_SYNCHRONOUS=2,
-                                 DEFAULT_WAL_AUTOCHECKPOINT=1000, DEFAULT_WAL_SYNCHRONOUS=1,
-                                 DEFAULT_WORKER_THREADS=0, ENABLE_API_ARMOR, ENABLE_BYTECODE_VTAB,
-                                 ENABLE_COLUMN_METADATA, ENABLE_DBSTAT_VTAB, ENABLE_FTS3,
-                                 ENABLE_FTS3_PARENTHESIS, ENABLE_FTS3_TOKENIZER, ENABLE_FTS4, ENABLE_FTS5,
-                                 ENABLE_LOCKING_STYLE=1, ENABLE_NORMALIZE, ENABLE_PREUPDATE_HOOK,
-                                 ENABLE_RTREE, ENABLE_SESSION, ENABLE_SNAPSHOT, ENABLE_SQLLOG,
-                                 ENABLE_STMT_SCANSTATUS, ENABLE_UNKNOWN_SQL_FUNCTION,
-                                 ENABLE_UPDATE_DELETE_LIMIT, HAS_CODEC_RESTRICTED, HAVE_ISNAN,
+                                 DEFAULT_WAL_AUTOCHECKPOINT=1000, DEFAULT_WAL_SYNCHRONOUS=2,
+                                 DEFAULT_WORKER_THREADS=0, ENABLE_COLUMN_METADATA, ENABLE_FTS3,
+                                 ENABLE_FTS3_PARENTHESIS, ENABLE_FTS4, ENABLE_FTS5, ENABLE_GEOPOLY,
+                                 ENABLE_MATH_FUNCTIONS, ENABLE_PREUPDATE_HOOK, ENABLE_RTREE, ENABLE_SESSION,
                                  MALLOC_SOFT_LIMIT=1024, MAX_ATTACHED=10, MAX_COLUMN=2000,
                                  MAX_COMPOUND_SELECT=500, MAX_DEFAULT_PAGE_SIZE=8192, MAX_EXPR_DEPTH=1000,
-                                 MAX_FUNCTION_ARG=127, MAX_LENGTH=2147483645, MAX_LIKE_PATTERN_LENGTH=50000,
-                                 MAX_MMAP_SIZE=1073741824, MAX_PAGE_COUNT=1073741823, MAX_PAGE_SIZE=65536,
+                                 MAX_FUNCTION_ARG=127, MAX_LENGTH=1000000000, MAX_LIKE_PATTERN_LENGTH=50000,
+                                 MAX_MMAP_SIZE=0x7fff0000, MAX_PAGE_COUNT=1073741823, MAX_PAGE_SIZE=65536,
                                  MAX_SQL_LENGTH=1000000000, MAX_TRIGGER_DEPTH=1000,
-                                 MAX_VARIABLE_NUMBER=500000, MAX_VDBE_OP=250000000, MAX_WORKER_THREADS=8,
-                                 MUTEX_UNFAIR, OMIT_AUTORESET, OMIT_LOAD_EXTENSION, STMTJRNL_SPILL=131072,
-                                 SYSTEM_MALLOC, TEMP_STORE=1, THREADSAFE=2, USE_URI
+                                 MAX_VARIABLE_NUMBER=250000, MAX_VDBE_OP=250000000, MAX_WORKER_THREADS=8,
+                                 MUTEX_PTHREADS, SYSTEM_MALLOC, TEMP_STORE=1, THREADSAFE=1

DEFAULT_WAL_SYNCHRONOUS is the only change that jumps out to me as a possible root cause. The sqlite docs don't seem to suggest that using 1 vs 2 would have this kind of effect, but I'm out of my element and not an expert here:

@nedbat
Copy link
Owner

nedbat commented Apr 25, 2023

#1605 reports the same issue with journal files interfering with combining.

@nedbat
Copy link
Owner

nedbat commented Sep 30, 2023

Coming back to this, I decided that explicitly ignoring *-journal files is a fine fix, and an easy one. It's in commit 7c25ba0. On Python 3.12, we can now configure SQLite to allow us to disable journal writing, which I've done in commit 8624ce9.

@nedbat nedbat closed this Sep 30, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants