Steps to Reproduce:
1. On the DS Console, Configuration tab | expand Data, choose a backend icon in
2. Right click and choose "initialize database", put an LDIF file name and
3. Once the import started, click Stop on the "initialize
window, which crashed the server
Task can be cancelled by sending a modify request on the task entry by
replacing nsTaskCancel value with TRUE as long as the task has the cancel
handling code. Currently, only import does.
Once TRUE is set to nsTaskCacnel, the pre-set callback slapi_task_set_cancel_fn
(import_task_abort in this case) is called and set the ABORT flag, which is
monitored by import_monitor_threads. By returning from import_monitor_threads,
the main import threads calls slapi_task_log_status. This function calls
slapi_task_status_changed, where since the task is cancelled, it sets
destroy_task to the event queue. That is, any time after the first
slapi_task_log_status/slapi_task_status_changed call, the task may be
destroyed. On the other hand, the task application import tries to log after
[..] - import userRoot: Aborting all import threads...<== first log after
[..] - import userRoot: Import threads aborted.
[..] - import userRoot: Closing files...
!!! slapi_task_finish is called !!!
[..] - import userRoot: Import failed.
In this scenario, any logging or slapi_task_finish after the first log could
crash the server.
We should not go into the task clean up code when the state is just cancelled.
Rather, we should let the task application finish the task which changes the
state to finished, then destroy the task.