Summary
In the Linux console image, backtest (and optimize) with --data-mode=m1-csv or --data-mode=tick-csv never delivers a single bar to the cBot. The bot instance starts, then after 3–5 minutes the console reports process stopped responding and was terminated (sometimes aborted by timeout) and writes a report with empty values. The identical command with --data-mode=m1 or --data-mode=open finishes in seconds.
Root cause (from a runtime exception trace and the decompiled assemblies): when answering the bot host's symbol subscription, the console shares the memory-mapped CSV with the out-of-process bot host through SystemCalls.SetInheritable / SystemCalls.DuplicateHandle, which are [DllImport("kernel32.dll")]. On Linux this throws System.DllNotFoundException, the handler dies, the reply is never sent, and the bot host times out.
Environment
- Image:
ghcr.io/spotware/ctrader-console tags 5.4, 5.5.17, 5.6.8, 5.7.10, 5.9.11, 5.10.1, 5.10.2-alpha and latest (all reproduce)
- Platform: linux/arm64 (Docker Desktop on macOS), also reproduced under linux/amd64
- .NET runtime in the image: 10.0.9 (5.10.1)
- Accounts: a live account and a Spotware demo account (both reproduce); symbols EURUSD and BTCUSD; periods m1 and m5
- Bots: a generated bot, a trivial "buy once in OnBar then Stop()" bot, and a minimal bot that only prints in OnStart (OnStart is never reached)
Steps to reproduce
- Create
data.csv in the documented M1 format, covering 2024-01-02 and 2024-01-03 completely (no header):
2024.01.02,00:00,1.10366,1.10376,1.10366,1.10374,102
2024.01.02,00:01,1.10371,1.10375,1.10368,1.10375,74
...
2024.01.03,23:59,1.09253,1.09260,1.09253,1.09258,17
- Run:
docker run --rm -v $PWD:/work ghcr.io/spotware/ctrader-console:5.10.1 \
backtest /work/AnyBot.algo --ctid=... --pwd-file=/work/pwd --account=... \
--symbol=EURUSD --period=m5 --start=02/01/2024 --end=03/01/2024 --balance=10000 \
--data-mode=m1-csv --data-file=/work/data.csv --report-json=/work/report.json --exit-on-stop
- Compare with the same command using
--data-mode=m1.
Expected
The backtest runs on the CSV bars and produces a report, as with --data-mode=m1.
Actual
Logged in.
Starting cBot...
Progress | Backtesting | 0.00 % |
Info | CBot instance [..., EURUSD, m5] started.
Error | CBot instance [..., EURUSD, m5] process stopped responding and was terminated.
{
"Equity":,
"NetProfit":-,
...
followed by System.InvalidOperationException: Message expected at ...BacktestReportSavingStateStrategy.DoEnter().
Same result with tick-csv (Date,Time,Bid,Ask file), with --spread, with --data-dir, with --cap-add SYS_PTRACE, with --security-opt seccomp=unconfined, with the CSV copied inside the image filesystem, and with a file containing a week of history before --start.
Diagnosis
Managed stacks of both processes during the stall (dotnet-stack):
- bot host (
algohost.netcore), main dispatcher thread:
SmallBacktestingRobotInstanceBase.InitializeBacktestingInstance → SmallBacktestingMarketData.GetChartSource → SmallSymbol.TrySubscribe → SmallSilentBacktestingMarketDataController.TrySubscribe → AutomateTargetRouter.SendAndWait (waiting for SilentBacktestingSubscribeSymbolResMessage)
- console:
AutomateArenaThreadDispatcher.DispatcherLoop idle; no thread doing any CSV work; the CSV file is not open in either process.
Exception events of the console process recorded with
DOTNET_EnableEventPipe=1 DOTNET_EventPipeConfig=Microsoft-Windows-DotNETRuntime:0x8000:5:
System.DllNotFoundException: Unable to load shared library 'kernel32.dll' or one of its dependencies. ...
/app/kernel32.dll: cannot open shared object file: No such file or directory
/app/libkernel32.dll.so: cannot open shared object file: No such file or directory
... (2 occurrences)
Code path (decompiled from 5.10.1):
cTrader.Automate.Instances.Backtesting.Controllers.MarketData.BigSilentBacktestingMarketDataController.HandleAsync(SilentBacktestingSubscribeSymbolReqMessage)
→ LoadAsync(...) (succeeds)
→ BacktestingCsvDataSourceMapService.MapIfNeeded(dataSource, _sharedResources)
→ MemoryMappedFile.CreateFromFile(csvFilePath) then OutProcSharedResources.ShareHandle(handle)
→ SystemCalls.SetInheritable(...) / SystemCalls.DuplicateHandle(...)
→ [DllImport("kernel32.dll")] SetHandleInformation / DuplicateHandle → DllNotFoundException
SystemCalls is the only ISystemCalls export; cTrader.Automate.Infrastructure.Linux.dll and cTrader.Console.Infrastructure.Linux.dll do not provide a Linux implementation.
- Because the exception escapes
HandleAsync after the LoadAsync try/catch, _router.Send(new SilentBacktestingSubscribeSymbolResMessage(...)) is never reached.
Second, related issue: silent hang before the bot starts
If the CSV does not cover the whole requested range by calendar day (e.g. --end=04/01/2024 with a file whose last bar is 2024.01.03,23:59), or the file cannot be parsed at all (e.g. a file containing this,is,not,a,csv), the process hangs forever after Logged in. without any message. The failed BacktestingCsvDataSourceService.GetMinMaxDateAsync / CsvBarsReadFailed result is never reported. Only a nonexistent --data-file is rejected (Can't find file specified for --data-file parameter!). Please surface these errors and exit.
Suggested fix
Provide a Linux implementation of ISystemCalls (or avoid handle duplication for the CSV mapping, e.g. let the bot host open the CSV path itself, since it already receives the path), and make CSV load failures fail fast with a message.
Summary
In the Linux console image,
backtest(andoptimize) with--data-mode=m1-csvor--data-mode=tick-csvnever delivers a single bar to the cBot. The bot instance starts, then after 3–5 minutes the console reportsprocess stopped responding and was terminated(sometimesaborted by timeout) and writes a report with empty values. The identical command with--data-mode=m1or--data-mode=openfinishes in seconds.Root cause (from a runtime exception trace and the decompiled assemblies): when answering the bot host's symbol subscription, the console shares the memory-mapped CSV with the out-of-process bot host through
SystemCalls.SetInheritable/SystemCalls.DuplicateHandle, which are[DllImport("kernel32.dll")]. On Linux this throwsSystem.DllNotFoundException, the handler dies, the reply is never sent, and the bot host times out.Environment
ghcr.io/spotware/ctrader-consoletags 5.4, 5.5.17, 5.6.8, 5.7.10, 5.9.11, 5.10.1, 5.10.2-alpha andlatest(all reproduce)Steps to reproduce
data.csvin the documented M1 format, covering 2024-01-02 and 2024-01-03 completely (no header):--data-mode=m1.Expected
The backtest runs on the CSV bars and produces a report, as with
--data-mode=m1.Actual
followed by
System.InvalidOperationException: Message expected at ...BacktestReportSavingStateStrategy.DoEnter().Same result with
tick-csv(Date,Time,Bid,Askfile), with--spread, with--data-dir, with--cap-add SYS_PTRACE, with--security-opt seccomp=unconfined, with the CSV copied inside the image filesystem, and with a file containing a week of history before--start.Diagnosis
Managed stacks of both processes during the stall (
dotnet-stack):algohost.netcore), main dispatcher thread:SmallBacktestingRobotInstanceBase.InitializeBacktestingInstance→SmallBacktestingMarketData.GetChartSource→SmallSymbol.TrySubscribe→SmallSilentBacktestingMarketDataController.TrySubscribe→AutomateTargetRouter.SendAndWait(waiting forSilentBacktestingSubscribeSymbolResMessage)AutomateArenaThreadDispatcher.DispatcherLoopidle; no thread doing any CSV work; the CSV file is not open in either process.Exception events of the console process recorded with
DOTNET_EnableEventPipe=1 DOTNET_EventPipeConfig=Microsoft-Windows-DotNETRuntime:0x8000:5:Code path (decompiled from 5.10.1):
cTrader.Automate.Instances.Backtesting.Controllers.MarketData.BigSilentBacktestingMarketDataController.HandleAsync(SilentBacktestingSubscribeSymbolReqMessage)→
LoadAsync(...)(succeeds)→
BacktestingCsvDataSourceMapService.MapIfNeeded(dataSource, _sharedResources)→
MemoryMappedFile.CreateFromFile(csvFilePath)thenOutProcSharedResources.ShareHandle(handle)→
SystemCalls.SetInheritable(...)/SystemCalls.DuplicateHandle(...)→
[DllImport("kernel32.dll")] SetHandleInformation/DuplicateHandle→DllNotFoundExceptionSystemCallsis the onlyISystemCallsexport;cTrader.Automate.Infrastructure.Linux.dllandcTrader.Console.Infrastructure.Linux.dlldo not provide a Linux implementation.HandleAsyncafter theLoadAsynctry/catch,_router.Send(new SilentBacktestingSubscribeSymbolResMessage(...))is never reached.Second, related issue: silent hang before the bot starts
If the CSV does not cover the whole requested range by calendar day (e.g.
--end=04/01/2024with a file whose last bar is2024.01.03,23:59), or the file cannot be parsed at all (e.g. a file containingthis,is,not,a,csv), the process hangs forever afterLogged in.without any message. The failedBacktestingCsvDataSourceService.GetMinMaxDateAsync/CsvBarsReadFailedresult is never reported. Only a nonexistent--data-fileis rejected (Can't find file specified for --data-file parameter!). Please surface these errors and exit.Suggested fix
Provide a Linux implementation of
ISystemCalls(or avoid handle duplication for the CSV mapping, e.g. let the bot host open the CSV path itself, since it already receives the path), and make CSV load failures fail fast with a message.