Skip to content

Improving exception handling and logging in libsyclinterface #677

Closed
@diptorupd

Description

@diptorupd

Related #35 #628 #351

The issue relates to an overhaul of the exception handling design in the libsyclinterface helper library.

Background

libsyclinterface tries to follow the so-called Abrahams Guarantees design for exception handling. Our intent is to ensure:

  1. No throw: No C++ exceptions will be raised inside libsyclinterface, i.e., all exceptions should be caught.
  2. Basic exception safety: No resources should be leaked in the case of an exception. All previously allocated resources in the function prior to encountering an exception should get freed inside the catch block. (Note: Klockwork is able to catch these issues.)
  3. Strong exception safety: Rollback of any externally visible side-effects. If an argument passed into a function was updated prior to encountering the exception, it should be reverted back to its original value.
  4. No guarantees: 😃

Requirements

  1. Ensure proper exception safety is implemented in libsyclinterface by auditing the code and adding negative test cases.

  2. Make the handling of exceptions more informative and user configurable.
    Currently, libsyclinterface only prints out the exception message inside a catch block. The behavior is very rudimentary and not configurable at all. Instead, we can introduce a handler function that can log exceptions in different ways, such as print out messages with different levels of verbosity or even write them to a file. The handler function should be added to the helper directory.
    We can use a library such as Boost Log for this purpose. Boost logs allows creating a global logger that I believe is thread safe. Most probably we can control the logger behavior using environment variables.

  3. We are repeating the same code in every function in libsyclinterface. Instead, a better way can be to just catch std::exception and then pass the exception object to the handler function. We can introduce a big switch inside the handler as shown in the following snippet . Doing so will also address Update sycl interface library to use SYCL 2020 exceptions #628.

// a_sycl2020_conformant.cpp
#include <CL/sycl.hpp>
#include <iostream>

int main(void) {
  sycl::device d;

  try {
     sycl::device pd = d.get_info<sycl::info::device::parent_device>();
  } catch (const sycl::exception &e) {
     handler(e);
  }
  return 0;
}
/*
void handler(const std::exception &e) {
     if (e.category() == sycl::sycl_category() && e.code() == sycl::errc::runtime) {
        std::cerr << "No parent" << std::endl;
     } else {
        std::cerr << "Unknown exception occurred: " << ex.what() << std::endl;
        std::terminate();
     }
}
*/
  1. C++ allows writing code such as throw 1, so technically not all exceptions are std::exception objects. We should evaluate if handling of non-std::exception objects is required (Improve exception handling inside libsyclinterface #351). I seriously doubt SYCL/dpcpp_cpp_rt is going to do any such a thing, but maybe we can add a special handler to catch all non-std::exception objects?
  2. Make it possible to see the exact file, function, and line where the exception was thrown either using BOOST.log or directly by using the __FILE__, __func__, __LINE__ macros.

Subtasks:

Metadata

Metadata

Labels

libsyclinterfaceIssues related to libsyclinterface

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions