Skip to content

Fixed coverity issues in acl_hal_mmd.cpp #227

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

haoxian2
Copy link
Contributor

@haoxian2 haoxian2 commented Dec 9, 2022

Fixed coverity issues in acl_hal_mmd.cpp: Type: Resource leak (RESOURCE_LEAK)

mmd_libraries were not closed after execution, which causes memory leaks. But mmd_libraries cannot be closed trivially since closing the library invalidates the symbol return by dlsym(), which means calling the function further down is undefined behaviour.
To solve this issues, I added a dl_wrapper_t struct as a global initialized wrapper that would be deallocated when closing the runtime library. This wrapper would contain all the opened libraries in a vector that would be closed by the destructor of dl_wrapper_t before the vector deallocates.

@haoxian2 haoxian2 requested a review from pcolberg December 9, 2022 17:53
@haoxian2
Copy link
Contributor Author

haoxian2 commented Dec 9, 2022

In the original code, there is this if-statement starting at line 581:

auto *test_symbol =
      my_dlsym(mmd_library, "aocl_mmd_get_offline_info", &error_msg);
  if (!test_symbol) {
    // On Linux, for custom libraries close the library (which was opened
    // locally) and then reopen globally. For Windows, there is no option (i.e.
    // it is always global)
#ifdef __linux__
    my_dlclose(mmd_library);
    ACL_HAL_DEBUG_MSG_VERBOSE(
        1, "This library is a custom library. Opening globally.\n");
    mmd_library = my_dlopen_global(library_name, &error_msg);
    if (!mmd_library) {
      std::cout << "Error: Could not load custom library " << library_name;
      if (error_msg && error_msg[0] != '\0') {
        std::cout << " (error_msg: " << error_msg << ")";
      }
      std::cout << "\n";
      return CL_FALSE;
    }
#endif
  } else {
    if (load_libraries) {
      # ....... load the library .......
    }
    ++num_boards_found;
  }
return CL_TRUE;

As you can see, in the even that !test_symbol is true, we do mmd_library = my_dlopen_global(library_name, &error_msg), but we are not doing anything with this opened library since after it is allocated, it falls off of the if-statement and the function immediately returns. Do you know what this block is intended to do?

@haoxian2 haoxian2 requested a review from zibaiwan December 9, 2022 17:59
@pcolberg pcolberg added the bug Something isn't working label Dec 10, 2022
@pcolberg pcolberg added this to the 2023.1 milestone Dec 10, 2022
@@ -1168,6 +1169,7 @@ static acl_mmd_dispatch_t *get_msim_mmd_layer() {
return nullptr;
}
auto *sym = my_dlsym(mmd_lib, sym_name, &error_msg);
my_dlclose(mmd_lib);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closing the library invalidates the symbol return by dlsym(), which means calling the function further down is undefined behaviour. These dlopen()-related leaks are likely nontrivial to fix and require a redesign. You could start with a RAII-safe wrapper, e.g.,

struct dl_wrapper {
  dl_wrapper(...) { this->handle = dlopen(...); }
  ~dl_wrapper() { dlclose(this->handle); }
  // prohibit copying to avoid double-close of handle
  dl_wrapper(const dl_wrapper &) = delete;
  dl_wrapper &operator=(const dl_wrapper &) = delete;
  void *sym(...) { return dlsym(this->handle, ...); }
};

The nontrivial part is where to store the wrapper object to ensure the symbols remain valid over the lifetime of their intended use. Maybe there is an easier solution to avoid the resource leak?

Copy link
Contributor Author

@haoxian2 haoxian2 Dec 16, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The solution I proposes in this PR is to keep track of the opened libraries with a wrapper of a vector of mmd_libs in the global scope. The wrapper would be similar to the one you proposed. The vector would deallocate with the closing of the runtime library, and all the libraries present inside will close themselves through the destructor.

I got this vector idea from std::vector<acl_mmd_dispatch_t> internal_mmd_dispatch. This vector is where all the symbols end up going and is declared as a global vector in the .cpp file.

Copy link
Contributor

@pcolberg pcolberg Jan 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @haoxian2, this is going in the right direction. The RAII wrapper should fully encapsulate the management of the resource; ideally, the constructor acquires the resource, currently my_dlopen(), and the destructor releases the resource, currently my_dlclose().

However, the situation here is slightly more complicated by the presence of two methods to load the library, my_dlopen() versus my_dlopen_global(). Let me take a detailed look at this issue before working out a solution.

@haoxian2 haoxian2 force-pushed the coverity-acl-hal-mmd branch 3 times, most recently from 4fbcebc to 539f27b Compare December 16, 2022 19:26
@haoxian2 haoxian2 requested a review from pcolberg December 16, 2022 19:32
@haoxian2 haoxian2 force-pushed the coverity-acl-hal-mmd branch 2 times, most recently from a11a652 to e909e10 Compare December 19, 2022 20:54
@pcolberg pcolberg modified the milestones: 2023.1, 2023.2 Dec 23, 2022
@pcolberg pcolberg force-pushed the coverity-acl-hal-mmd branch from e909e10 to 84bf6c3 Compare January 24, 2023 23:44
@pcolberg pcolberg assigned pcolberg and unassigned haoxian2 Jan 25, 2023
@pcolberg pcolberg marked this pull request as draft January 26, 2023 00:48
@pcolberg pcolberg force-pushed the coverity-acl-hal-mmd branch 2 times, most recently from f4f66a1 to aa1b484 Compare January 27, 2023 00:33
@pcolberg pcolberg force-pushed the coverity-acl-hal-mmd branch from f72927c to 564b19e Compare February 2, 2023 01:39
@pcolberg pcolberg force-pushed the coverity-acl-hal-mmd branch 2 times, most recently from 7a7b907 to c6df82c Compare February 17, 2023 03:47
pcolberg and others added 2 commits February 17, 2023 11:42
This is a cosmetic change only to prepare the next commit.
mmd_libraries were not closed after execution, which causes memory leaks. But mmd_libraries cannot be closed trivially since closing the library invalidates the symbol return by dlsym(), which means calling the function further down is undefined behaviour.
To solve this issues, I added a `dl_wrapper_t` vector as a global initialized vector that would be deallocated when closing the runtime library. This vector would contain all the opened libraries that would be closed by the destructor of `dl_wrapper_t` once the vector deallocates.
@zibaiwan zibaiwan modified the milestones: 2023.2, 2024.0 May 29, 2023
@zibaiwan zibaiwan closed this Aug 17, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants