Browse Source

storage: make partial writes pos sanity-check more robust

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)
```
master
SomberNight 2 years ago
parent
commit
bfba0dba56
No known key found for this signature in database
GPG Key ID: B33B5F232C6271E9
  1. 14
      electrum/storage.py

14
electrum/storage.py

@ -69,8 +69,8 @@ class WalletStorage(Logger):
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()
@ -86,8 +86,9 @@ class WalletStorage(Logger):
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:
@ -105,10 +106,11 @@ class WalletStorage(Logger):
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())

Loading…
Cancel
Save