Skip to content

Commit 4c7e23d

Browse files
committed
Fixed win32 checkpoint resume SEGFAULT
1 parent b291c08 commit 4c7e23d

File tree

2 files changed

+32
-2
lines changed

2 files changed

+32
-2
lines changed

src/tribler/core/libtorrent/download_manager/download_manager.py

+9-2
Original file line numberDiff line numberDiff line change
@@ -732,9 +732,16 @@ async def start_handle(self, download: Download, atp: dict) -> None:
732732
resume_data = atp.get("resume_data")
733733
if resume_data:
734734
atp_resume_data_skipped["resume_data"] = "<skipped in log>"
735-
logger.info("Start handle. Download: %s. Atp: %s", str(download), str(atp_resume_data_skipped))
736-
if resume_data:
735+
try:
736+
resume_data_dict = cast(dict[bytes, Any], lt.bdecode(resume_data))
737+
# If the save_path is None or "" win32 SEGFAULTS, see https://github.com/Tribler/tribler/issues/8353
738+
if not resume_data_dict.get(b"save_path"):
739+
resume_data_dict[b"save_path"] = atp.get("save_path", ".").encode()
740+
atp["resume_data"] = lt.bencode(resume_data_dict)
741+
except RuntimeError:
742+
atp.pop("resume_data")
737743
logger.debug("Download resume data: %s", str(atp["resume_data"]))
744+
logger.info("Start handle. Download: %s. Atp: %s", str(download), str(atp_resume_data_skipped))
738745

739746
ltsession = await self.get_session(download.config.get_hops())
740747
infohash = download.get_def().get_infohash()

src/tribler/test_unit/core/libtorrent/download_manager/test_download_manager.py

+23
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from pathlib import Path
77
from unittest.mock import AsyncMock, MagicMock, Mock, call, patch
88

9+
import libtorrent
910
from configobj import ConfigObj
1011
from configobj.validate import Validator, VdtParamError
1112
from ipv8.test.base import TestBase
@@ -186,6 +187,28 @@ async def test_start_handle_wait_for_dht(self) -> None:
186187

187188
self.assertTrue(task.done())
188189

190+
async def test_start_handle_empty_save_path(self) -> None:
191+
"""
192+
Test if the "save_path" is always set in the resume_data, otherwise we SEGFAULT on win32!
193+
"""
194+
download = Download(TorrentDef.load_from_memory(TORRENT_WITH_DIRS_CONTENT), None,
195+
checkpoint_disabled=True, config=self.create_mock_download_config())
196+
download.handle = Mock(is_valid=Mock(return_value=True))
197+
self.manager.get_session = AsyncMock(return_value=Mock(get_torrents=Mock(return_value=[])))
198+
self.manager._async_add_torrent = AsyncMock() # noqa: SLF001
199+
200+
await self.manager.start_handle(download, {
201+
"save_path": "/test_path/",
202+
"resume_data": libtorrent.bencode({b"file-format": b"libtorrent resume file", b"file-version": 1})
203+
}) # Schedule async_add_torrent
204+
await sleep(0) # Run async_add_torrent
205+
206+
session, infohash, atp = self.manager._async_add_torrent.call_args[0] # noqa: SLF001
207+
208+
self.assertIn("resume_data", atp)
209+
self.assertIn(b"save_path", libtorrent.bdecode(atp["resume_data"]))
210+
self.assertEqual(b"/test_path/", libtorrent.bdecode(atp["resume_data"])[b"save_path"])
211+
189212
async def test_start_download_existing_handle(self) -> None:
190213
"""
191214
Test if torrents can be added when there is a pre-existing handle.

0 commit comments

Comments
 (0)