otp icon indicating copy to clipboard operation
otp copied to clipboard

On-halt and delayed halt support for NIFs

Open rickard-green opened this issue 2 years ago • 1 comments

New NIF Functions

int enif_enable_delay_halt(ErlNifEnv *caller_env)

Enable delay of a runtime system halt that has flushing enabled until all calls to NIFs in the NIF library have returned. On success zero will be returned, and on failure a non zero value will be returned. If the delay halt feature has not been enabled, the runtime system may halt while a process is executing a NIF in the NIF library.

The runtime system halts when one of the erlang:halt() BIFs are called. By default flushing is enabled, but can be disabled using the erlang:halt/2 BIF. When flushing has been disabled, the delay halt setting will have no effect (that is, the runtime system will halt without waiting for NIFs to return), no atexit/on_exit handlers installed in the runtime system will be executed, and no outstanding I/O will be flushed.

enif_enable_delay_halt() can only be called inside a NIF library load() or upgrade() call, and will fail if called somewhere else. That is, it can only be called during loading of a NIF library. It can also only be called once. That is, the delay halt setting cannot be changed once it has been enabled. The delay halt setting is tied to the module instance with which the NIF library instance has been loaded. That is, in case both a new and old version of a module using the NIF library are loaded, they can have the same or different delay halt settings.

The delay halt feature can be used in combination with an on_halt() callback. The on_halt() callback is in this case typically used to notify processes blocked in NIFs in the library that it is time to return in order to let the runtime system complete the halting. Such NIFs should be dirty NIFs, since ordinary NIFs should never block for a long time.

int enif_install_on_halt_handler(ErlNifEnv *caller_env, void (*on_halt)(void *priv_data)))

Install a callback that will be called when the runtime system halts with flushing enabled. On success zero will be returned, and on failure a non zero value will be returned.

The runtime system halts when one of the erlang:halt() BIFs are called. By default flushing is enabled, but can be disabled using the erlang:halt/2 BIF. When flushing has been disabled, no on_halt() handlers will be called, no atexit/on_exit handlers installed in the runtime system will be called, and no outstanding I/O will be flushed.

enif_install_on_halt_handler() can only be called inside a NIF library load() or upgrade() call, and will fail if called somewhere else. That is, it can only be called during loading of a NIF library. When unloading the NIF library during a purge, an installed on_halt() handler will be uninstalled. enif_install_on_halt_handler() can also only be called once. That is, the on_halt() callback cannot be changed or removed once it has been installed by any other means than purging the module instance that loaded the NIF library. The on_halt() callback is tied to the module instance with which the NIF library instance has been loaded. That is, in case both a new and old version of a module using the NIF library are loaded, they can have one on_halt() callback installed each.

When the installed on_halt() callback is called, it will be passed a pointer to priv_data as argument. The priv_data pointer can be set when loading the NIF library.

The on_halt() callback can be used in combination with delay of halt until all calls into the library have returned. The on_halt() callback is in this case typically used to notify that processes blocked in NIFs in the library that it is time to return in order to let the runtime system complete the halting. Such NIFs should be dirty NIFs, since ordinary NIFs should never block for a long time.

Changed Functionality

erlang:halt/2

As of this change, exiting without flushing also implies that no atexit/on_exit handlers installed in the runtime system will be executed.


Closes #5325

rickard-green avatar Oct 14 '22 12:10 rickard-green

CT Test Results

       3 files     132 suites   46m 28s :stopwatch: 1 510 tests 1 460 :heavy_check_mark: 50 :zzz: 0 :x: 1 914 runs  1 845 :heavy_check_mark: 69 :zzz: 0 :x:

Results for commit 988a0e9f.

:recycle: This comment has been updated with latest results.

To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass.

See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally.

Artifacts

// Erlang/OTP Github Action Bot

github-actions[bot] avatar Oct 14 '22 12:10 github-actions[bot]

Is this something that can be merged to maint branch?

jaher avatar Nov 03 '22 16:11 jaher

We don't want to release this as a patch on OTP 25 since it introduces an incompatibility (the change in behaviour of halt() when flush has been disabled).

rickard-green avatar Nov 04 '22 15:11 rickard-green