Skip to content
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

Used in Windows DLL, FreeLibrary() hangs host program on unloading DLL. #251

Open
PolyVinalDistillate opened this issue Sep 22, 2023 · 2 comments

Comments

@PolyVinalDistillate
Copy link

PolyVinalDistillate commented Sep 22, 2023

In a DLL with a single function executing the following test code after being loaded with LoadLibrary():

void DLL_EXPORT IdentifierFunction(char** sBuf)
{
  *sBuf = (char*)sPluginID;  //Simply returns sPluginID

  printf("\n\nHello from TensorFlow C library version %s\n", TF_Version());
  auto a = cppflow::tensor({1.0, 2.0, 3.0});
  auto b = cppflow::fill({3}, 1.0);

  printf("Testing CPPFlow Tensor Addition Example\n");
  auto c = a+b;
  std::cout << c << std::endl;
  printf("\n\n");
}

I find that a subsequent call in the host program to FreeLibrary() hangs the execution.

If I append the following to the end of the above function:
TFE_DeleteContext(cppflow::context::get_context());

Then I can call FreeLibrary() without issue. I'm totally new to all this, so sorry if I'm missing something - but I feel like there's a bug here, as I saw a similar issue was closed last year due to inactivity.

P.S. trying to delete the context in DllMain() DLL_PROCESS_DETACH does not work, and neither does storing the TFE_Context* in a global variable to delete it later in DLL_PROCESS_DETACH.

@PolyVinalDistillate PolyVinalDistillate changed the title Used in Windows DLL, FreeLibrary() hangs on unloading DLL. Used in Windows DLL, FreeLibrary() hangs host program on unloading DLL. Sep 22, 2023
@PolyVinalDistillate
Copy link
Author

Addition of TFE_DeleteContext(cppflow::context::get_context()); does occasionally cause hard crash (which is arguably bertter than total hang!).

@PolyVinalDistillate
Copy link
Author

PolyVinalDistillate commented Sep 22, 2023

I've used a dirty hack for now that solves my problem with minimal resistance and maximum bad practise! Hopefully it will help with working out what the "correct" fix should look like.

  1. I've added a function to cppflow::context:
    void destroyContext(){if(this->tfe_context!=nullptr){TFE_DeleteContext(this->tfe_context);}this->tfe_context=nullptr;};
  2. I've adjusted the destructor in cppflow::context:
inline context::~context() {
  if(this->tfe_context!=nullptr)
    TFE_DeleteContext(this->tfe_context);
}
  1. I've added a function to my dll file that my host program always calls before calling FreeLibrary():
void DLL_EXPORT CleanupFunction()
{
  cppflow::get_global_context().destroyContext();
}
  1. I've executed cppflow::get_global_context(); in my DllMain() DLL_PROCESS_ATTACH to ensure there's a context created as soon as the DLL file is loaded with LoadLibrary().

I'd like to implement the "correct" fix myself in keeping with the programming style used here, however I'm afraid a lot of the C++ code looks pretty alien to me. For example, no matter how much I read up on it, the line std::unique_ptr<TFE_Op, decltype(&TFE_DeleteOp)> op(TFE_NewOp(context::get_context(), "Fill", context::get_status()), &TFE_DeleteOp); might as well be written in forth! Should I find the time, I may someday master these strange constructs. It's the Standard Template Libraries - they break my brain!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant