Missing finalization in Next.Core.Promises causes Access Violation on application shutdown

Summary

Next.Core.Promises.pas creates a TPromiseScheduler with 10+ worker threads in its initialization section but has no finalization section to clean them up. This causes EAccessViolation crashes during application shutdown because the promise threads are still running while Delphi's @Halt0 destroys forms and other objects.

Steps to Reproduce

  1. Use any TMS FNC component that references Next.Core.Promises (e.g. TTMSFNCGoogleMaps, TTMSFNCWebBrowser)

  2. Run the application normally for some time

  3. Close the application

Expected Behavior

Application shuts down cleanly. All promise threads are terminated before forms are destroyed.

Actual Behavior

EAccessViolation at address $00000000 ("Ausführung von Adresse 00000000") during shutdown. The promise threads are still active when @Halt0 starts destroying forms, leading to access violations on already-freed objects.

Background threads still running at crash time: 1x TThreadPool.TQueueWorkerThread, 10x TPromiseScheduler.TPromiseThread

Root Cause Analysis

In Next.Core.Promises.pas:

initialization
  CreatePromiseSchedulerIf;    // Creates TPromiseScheduler + starts 10+ threads

end.                           // No finalization!

The _Scheduler: IPromiseScheduler variable is never explicitly set to nil. Without a finalization section, the scheduler's reference count is not decremented before @Halt0 runs. The promise threads continue executing while Delphi tears down forms, VCL objects and other resources, causing access violations.

The TPromiseScheduler.Destroy already implements proper cleanup (signals FCancel, waits for controller, frees threads) — it just never gets called at the right time.

Suggested Fix

Add a finalization section:

initialization
  CreatePromiseSchedulerIf;

finalization
  _Scheduler := nil;

end.

Since _Scheduler is an IPromiseScheduler (interface reference), setting it to nil triggers reference counting, which calls TPromiseScheduler.Destroy, which properly signals all threads to stop and waits for them before the application continues with @Halt0.

Additional Note

The comment block at line 381-385 mentions a THelperDestroyFactory that should set _Scheduler to nil in its destructor, but this class does not exist in the current version of the unit. This suggests the cleanup mechanism was either removed or never fully implemented.

Hi,

Is this an AI generated summary? TTMSFNCGoogleMaps and TTMSFNCWebBrowser do not use promises internally. Are you trying to use it in combination with those?

Can you provide a sample what you are doing exactly when this access violation happens?

Hi, yes I analyzed my code with AI :wink: heres a corrected answer:

We are not using Promises directly. However, Next.Core.Promises is part of the TMSFNCCorePkg package. Our application uses VCL.TMSFNCGoogleMaps, VCL.TMSFNCWebBrowser, VCL.TMSFNCPlaces, VCL.TMSFNCGeocoding and VCL.TMSFNCDirections. Since these are part of TMS FNC, the TMSFNCCorePkg runtime package is loaded, which includes Next.Core.Promises.pas.

The initialization section of Next.Core.Promises.pas calls CreatePromiseSchedulerIf, which creates a TPromiseScheduler and starts worker threads immediately on unit load:

initialization
  CreatePromiseSchedulerIf;

We can confirm this by the MadExcept callstacks — every crash report shows 10x TPromiseScheduler.TPromiseThread running in the background, even though our code never creates or uses any promises.

Could you either:

  1. Add a finalization section (_Scheduler := nil;) to properly shut down the thread pool before @Halt0 runs?

  2. Or change the initialization to lazy-create the scheduler only when the first promise is actually used, rather than on unit load?

We are running on Windows Terminal Server with multiple concurrent users, which makes the timing-related crash more likely.

The Promise code belongs to Laurens, we’ll get in touch with him to see what can be done.

Hi,

You can expect the changes in this area in the next update.

Any news in this matters? Is the next update available?

Hi,

We have a release planned in the upcoming days, stay tuned.

1 Like

Good morning Tünde, when can we expect the next update with your fix?

Hi,

It appears the entry is missing in the version history but the changes should’ve been included in the 4.2.2.7 release from February 24th. Did you update and still experience issues?

thanks for that info. We will update and test.