RustiCL: Callbacks are not called upon errors
Enclosed a reproducer.
The problem is that callbacks are not called when events are completed with error states. However, on the clSetEventCallback ref page footnote 1 it says:
"The callback function registered for a command_exec_callback_type value of CL_COMPLETE will be called when the command has completed successfully or is abnormally terminated."
Note: The example should work because on clSetUserEventStatus ref page it is stated that errors can be set to user events:
"execution_status specifies the new execution status to be set and can be CL_COMPLETE or a negative integer value to indicate an error. A negative integer value causes all enqueued commands that wait on this user event to be terminated. clSetUserEventStatus can only be called once to change the execution status of event."
#include <iostream>
#include <cassert>
#include <CL/cl.h>
#define PLATFORM 0
#define DEVICE 0
void CL_CALLBACK
cb(cl_event trigger, cl_int event_command_status, void* user_data)
{
cl_int err_code;
// The following message will never be printed
std::cout << "Entering cb... (" << event_command_status << ")"
<< std::endl;
cl_event event = (cl_event)user_data;
err_code = clSetUserEventStatus(event, event_command_status);
assert(err_code == CL_SUCCESS);
err_code = clReleaseEvent(trigger);
assert(err_code == CL_SUCCESS);
std::cout << "Exiting cb..." << std::endl;
}
int main(int argc, char *argv[])
{
cl_int err_code;
cl_uint n;
// Get the platform
err_code = clGetPlatformIDs(0, NULL, &n);
assert(err_code == CL_SUCCESS);
assert(PLATFORM < n);
cl_platform_id* platforms = (cl_platform_id*)malloc(
n * sizeof(cl_platform_id));
assert(platforms);
err_code = clGetPlatformIDs(n, platforms, NULL);
assert(err_code == CL_SUCCESS);
cl_platform_id platform = platforms[PLATFORM];
free(platforms);
// Get the device
err_code = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, 0, NULL, &n);
assert(err_code == CL_SUCCESS);
assert(DEVICE < n);
cl_device_id* devices = (cl_device_id*)malloc(n * sizeof(cl_device_id));
assert(devices);
err_code = clGetDeviceIDs(platform, CL_DEVICE_TYPE_ALL, n, devices, NULL);
assert(err_code == CL_SUCCESS);
cl_device_id device = devices[DEVICE];
free(devices);
// Create a context
cl_context context = clCreateContext(
NULL, 1, &device, NULL, NULL, &err_code);
assert(err_code == CL_SUCCESS);
assert(context);
// Create a command_queue
const cl_queue_properties properties[1] = { 0 };
cl_command_queue queue = clCreateCommandQueueWithProperties(
context, device, properties, &err_code);
assert(err_code == CL_SUCCESS);
assert(queue);
// Create the trigger
cl_event trigger = clCreateUserEvent(context, &err_code);
assert(err_code == CL_SUCCESS);
assert(trigger);
// Create an user event to be set by the callback
cl_event finish = clCreateUserEvent(context, &err_code);
assert(err_code == CL_SUCCESS);
assert(finish);
// Register the callback
err_code = clSetEventCallback(
trigger, CL_COMPLETE, cb, (void*)finish);
assert(err_code == CL_SUCCESS);
// Trigger everything. If one sets CL_COMPLETE here the test works nicely
std::cout << "Triggering..." << std::endl;
err_code = clSetUserEventStatus(trigger, CL_OUT_OF_RESOURCES);
err_code = clFlush(queue);
assert(err_code == CL_SUCCESS);
// Wait for the callback
std::cout << "Waiting..." << std::endl;
err_code = clWaitForEvents(1, &finish);
assert(err_code == CL_EXEC_STATUS_ERROR_FOR_EVENTS_IN_WAIT_LIST);
std::cout << "All done!" << std::endl;
// Clean up
err_code = clReleaseEvent(finish);
assert(err_code == CL_SUCCESS);
err_code = clReleaseCommandQueue(queue);
assert(err_code == CL_SUCCESS);
err_code = clReleaseContext(context);
assert(err_code == CL_SUCCESS);
}