Skip to content

Commit

Permalink
storage: make partial writes pos sanity-check more robust
Browse files Browse the repository at this point in the history
The return value of f.write and f.seek cannot be compared when using open() in text mode:
```
>>> import os
>>> s = "aá"
>>>
>>> with open("a1", "w", encoding='utf-8') as f:
...   a = f.write(s)
...   pos = f.seek(0, os.SEEK_END)
...   print(a, pos)
...
2 3
>>>
>>> with open("a2", "wb") as f:
...   a = f.write(s.encode('utf-8'))
...   pos = f.seek(0, os.SEEK_END)
...   print(a, pos)
...
3 3
```

Was getting errors on Windows, probably due to `\r\n` vs `\n`?
```
20231010T121334.522573Z |    ERROR | util.CallbackManager | cb errored. event='adb_set_up_to_date'. exc=AssertionError((2471475, 2522998))
Traceback (most recent call last):
  File "...\electrum\electrum\wallet.py", line 497, in on_event_adb_set_up_to_date
    self.save_db()
  File "...\electrum\electrum\wallet.py", line 403, in save_db
    self.db.write()
  File "...\electrum\electrum\json_db.py", line 48, in wrapper
    return func(self, *args, **kwargs)
  File "...\electrum\electrum\json_db.py", line 389, in write
    self._append_pending_changes()
  File "...\electrum\electrum\json_db.py", line 48, in wrapper
    return func(self, *args, **kwargs)
  File "...\electrum\electrum\json_db.py", line 400, in _append_pending_changes
    self.storage.append(s)
  File "...\electrum\electrum\storage.py", line 110, in append
    assert pos == self.pos, (self.pos, pos)
AssertionError: (2471475, 2522998)
```
  • Loading branch information
SomberNight committed Oct 10, 2023
1 parent 6314330 commit bfba0db
Showing 1 changed file with 8 additions and 6 deletions.
14 changes: 8 additions & 6 deletions electrum/storage.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,8 @@ def __init__(self, path):
except IOError as e:
raise StorageReadWriteError(e) from e
if self.file_exists():
with open(self.path, "r", encoding='utf-8') as f:
self.raw = f.read()
with open(self.path, "rb") as f:
self.raw = f.read().decode("utf-8")
self.pos = f.seek(0, os.SEEK_END)
self.init_pos = self.pos
self._encryption_version = self._init_encryption_version()
Expand All @@ -86,8 +86,9 @@ def read(self):
def write(self, data: str) -> None:
s = self.encrypt_before_writing(data)
temp_path = "%s.tmp.%s" % (self.path, os.getpid())
with open(temp_path, "w", encoding='utf-8') as f:
self.pos = f.write(s)
with open(temp_path, "wb") as f:
f.write(s.encode("utf-8"))
self.pos = f.seek(0, os.SEEK_END)
f.flush()
os.fsync(f.fileno())
try:
Expand All @@ -105,10 +106,11 @@ def write(self, data: str) -> None:
def append(self, data: str) -> None:
""" append data to file. for the moment, only non-encrypted file"""
assert not self.is_encrypted()
with open(self.path, "r+", encoding='utf-8') as f:
with open(self.path, "rb+") as f:
pos = f.seek(0, os.SEEK_END)
assert pos == self.pos, (self.pos, pos)
self.pos += f.write(data)
f.write(data.encode("utf-8"))
self.pos = f.seek(0, os.SEEK_END)
f.flush()
os.fsync(f.fileno())

Expand Down

0 comments on commit bfba0db

Please sign in to comment.