On 30.05.2020 1:06, Julien Nabet wrote: > On 29/05/2020 17:19, Mike Kaganski wrote: >> On 29.05.2020 17:41, julien2412 wrote: >>> ... >> Ctor of ODriver should store the previous status if COM initialization, >> if it wants to re-initialize it with a specific concurrency. It should >> check the failure code to detect if it was rejected because of different >> mode (RPC_E_CHANGED_MODE); and if so, it should call CoUninitialize as >> many times as needed to succeed with CoInitializeEx; then it needs to >> additionally call CoInitializeEx the same number of times (so that the >> total number of initializations is increased by 1). Then in dtor, it >> should reverse that: if it hadn't needed to change mode in ctor, then >> just call CoUninitialize once; otherwise, call CoUninitialize as many >> times as needed to CoInitializeEx with old mode to succeed, then call >> CoInitializeEx as many times that total initialize count is decremented >> by 1 compared to before entering dtor. That should account for possible >> intermediate unpaired calls to CoInitialize(Ex)/CoUninitialize in the >> same thread, and make sure that the calling code is in ~consistent state >> ... (however even this is a hack, and it would be better to find out why >> does it need to change the mode at all - i.e., if we can make sure it >> always used in appartment-threaded code). > > Thank you for your feedback Mike. > > I submitted on gerrit https://gerrit.libreoffice.org/c/core/+/95174. > > Just quote the comment I put in gerrit: > > "It seems we don't need to count the number of times CoInitializeEx has > been called. From > https://docs.microsoft.com/en-us/windows/win32/learnwin32/error-handling-in-com: > "The success code S_FALSE deserves mention. Some methods use S_FALSE to > mean, roughly, a negative condition that is not a failure. It can also > indicate a "no-op"—the method succeeded, but had no effect. For example, > the CoInitializeEx function returns S_FALSE if you call it a second time > from the same thread" That document can't be completely correct, when compared to another one: https://docs.microsoft.com/en-us/windows/win32/api/combaseapi/nf-combaseapi-coinitializeex. It tells: "To close the COM library gracefully on a thread, each successful call to CoInitialize or CoInitializeEx, _including any call that returns S_FALSE_, must be balanced by a corresponding call to CoUninitialize". Note the "including any call that returns S_FALSE" part. If that call would be a no op, then the following would necessarily fail: CoInitializeEx(...); // Initializes COM on thread for the first time <some code using COM objects> <call to some function> ... CoInitializeEx(...); // returns S_FALSE - no-op? ... CoUninitialize(); // If the previous call was no-op, then it // actually uninitializes COM? return; <code in parent working with COM> // FAIL! COM not initialized! CoUninitialize(); But that must be the predominant pattern, and failing that would mean most existing COM code failing. In fact, each successful call to CoInitialize(Ex) - including S_FALSE (which is a success code), must increment some internal ref counter. This may be tested using something like this: main() { auto hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); assert(SUCCEEDED(hr)); hr = CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); assert(SUCCEEDED(hr)); CoUninitialize(); hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); assert(FAILED(hr)); CoUninitialize(); hr = CoInitializeEx(nullptr, COINIT_MULTITHREADED); assert(SUCCEEDED(hr)); } I haven't tried that, actually; what I wrote is speculation - but I suggest you to actually test that to make sure. Either "no-op" was an error, or just used in a very narrow sense (as "not actually calling initialization code") - I will file an issue there in the MS documentation, when I'm sure. -- Best regards, Mike Kaganski
Attachment:
pEpkey.asc
Description: application/pgp-keys
_______________________________________________ LibreOffice mailing list LibreOffice@xxxxxxxxxxxxxxxxxxxxx https://lists.freedesktop.org/mailman/listinfo/libreoffice