When is the correct time to call FreeLibraryWhenCallbackReturns?

When is the correct time to call Free­Library­When­Callback­Returns, or any of the other ...When­Callback­Returns functions? In practice, many people call the function immediately before returning from the callback. Is this a requirement?

No. You can call the ...When­Callback­Returns function at any time during the execution of your callback, but you can call each one at most once per callback instance. In other words, you cannot ask for two DLLs to be freed when the callback returns, but it's okay to ask for one DLL to be freed and one critical section to be exited. If you do ask for multiple things to happen when the callback returns, the order in which they occur is unspecified.

By convention, the ...When­Callback­Returns function is called immediately before the callback returns, because it matches the point at which you would have called the non-...When­Callback­Returns version. In other words, "I would have called Free­Library or Free­Library­And­Exit­Thread here, but I can't, so I'll call Free­Library­When­Callback­Returns instead, and then immediately return."

Of course, if you are worried that you might forget to call Free­Library­When­Callback­Returns in all your exit paths (a legitimate concern, in my opinion), you may choose to call it at the start of the work, so that you won't forget. It doesn't matter when you call it, as long as you do it inside the task at some point before you return.

Many happy returns. (Tomorrow is Boxing Day, you see.)

Comments (5)
  1. If you think about it from the perspective of the implementer of FreeLibraryWhenCallbackReturns, that’s the only possible way it could work. That function has no idea whether it’s being called from the beginning or end of your callback function — it can’t be inspecting the call stack to be making some kind of decision (well it *could* try to do that, but that’s a terrible idea and will break, and then what it would decide to do?).

    The only thing it can reasonably do is queue up work to be executed later, so it doesn’t matter if that work gets queued earlier or later in the execution of your callback.

    1. In theory, the state could be kept in some ephemeral thread-local state (like GetLastError) which gets wiped out by certain intervening calls. But yeah, the obvious place for the state is in the PTP_CALLBACK_INSTANCE.

      1. smf says:

        Does it only free the first or last one you register? If it’s the last then it can get wiped out by intervening tasks, i.e. if you call into a component that calls it without you knowing.

        1. Darran Rowe says:

          The documentation doesn’t specify what happens if you call it twice, so the behaviour is quite literally undocumented.
          There is a comment stating that it raises a structured exception though. Even though that is implementation defined behaviour, that really shows that it is an invalid situation to begin with.
          Anyway, depending on the situation, a component messing around with thread pool related stuff without you knowing is dangerous.

          1. smf says:

            “Anyway, depending on the situation, a component messing around with thread pool related stuff without you knowing is dangerous.”

            As a software developer you are always at the mercy of someone else who got a bonus by making something work, no matter the consequences. Who do you think your bosses respect more? The guy who got the bonus or the guy who complains that he can’t get any of his changes to work now.

Comments are closed.

Skip to main content