Why using "SND_SYNC" in a "QueueUserWorkItem" bad? - c++

Larry Osterman writes about a real error found in Microsoft's code, the offending code is
static DWORD WINAPI _PlayBeep(__in void* pv)
{
UNREFERENCED_PARAMETER(pv);
PlaySound(L".Default"NULL, SND_SYNC | SND_ALIAS);
return 0;
}
LRESULT WndProc(...)
{
:
:
case WM_KEYDOWN:
if (!_AcceptInputKeys(wParam, lParam))
{
QueueUserWorkItem(_PlayBeep, NULL, 0);
}
break;
}
and Larry asks:
Given the simplicity of the code
above, to get the answer right, it’s
not enough to say what’s wrong with
the code (the problem should be
blindingly obvious). You also need to
be able to explain why this is so bad
(in other words, what breaks when you
do this).
The best answer is terse in the comments is not enough,
David's VERY close to what's going
wrong - now think about the context of
the application.
Can someone please explain fully what's happening when this code runs?

Read the answer page, it's got a very detailed explanation
http://blogs.msdn.com/b/larryosterman/archive/2009/06/29/what-s-wrong-with-this-code-part-26-the-answer.aspx
Basically, don't use QueueUserWorkItem for long-running work items because this can cause thread exhaustion in your process, or even deadlock in a very hard to debug way if you wait for work items to complete on a (necessarily) finite-sized thread pool. Same goes for the .Net equivalent of this API ThreadPool.QueueUserWorkItem btw.
In this specific case, the workitem trigger ("press the down key") and the resulting thread workitem ("sound a sync beep") are very unbalanced, so that if user holds down or repeatedly hits his/her down key, the process will quickly hit fatal issues.

Related

How can I create a persistent list of globally accesible objects queried from threads?

I've been trying to get a persistent object from a thread for hours.
I want to write a shared library in C++ that starts a persistent loop in a function.
In the following code snippets there is a class called Process. Process initializes a TCP/IP interface to read and write data from a Simulink model.
This is only for declaration and should not be important for this problem, but now you know what I talk about when mentioning the processes.
main.cpp
I know, it looks kinda ugly/unprofessional, but I'm fairly new to C++..
// frustrated attempt to make everything persistent
static vector<std::thread> processThreads;
static ProcessHandle processHandle;
static vector<std::promise<Process>> promiseProcess;
static vector<std::future<Process>> futureProcess;
EXPORT int initializeProcessLoop(const char *host, int port)
{
std::promise<Process> promiseObj;
futureProcess.push_back(std::future<Process>(promiseObj.get_future()));
processThreads.push_back(std::thread(&ProcessHandle::addProcess, processHandle, host, port, &promiseProcess[0]));
Process val = futureProcess[0].get();
processHandle.handleList.push_back(val);
return (processHandle.handleList.size() - 1);
}
ProcessHandle.cpp
The addProcess function from ProcessHandle creates the Process that should be persistent, adds it to a static vector member of ProcessHandle and passes the promise to the execution loop.
int ProcessHandle::addProcess(const char *address, int port, std::promise<Process> * promiseObj) {
Process process(address, port);
handleList.push_back(process);
handleList[handleList.size() - 1].exec(promiseObj);
return handleList.size() - 1;
}
To the main problem now...
If I change "initializeProcessLoop" to include:
if(processHandle.handleList[0].isConnected())
{
processHandle.handleList[0].poll("/Compare To Constant/const");
}
after i've pushed "val" to the processHandle.handleList everything works fine and I can poll the data as it should be.
If I instead poll it from - for examle - the main function, the loop crashes inside of the "initializeProcessLoop" because "Process val" is reassigned (?) with futureProcess[0].get().
How can I get the Process variable and the threaded loop to be consistent after the function returns?
If there are any questions to the code (and I bet there will be), feel free to ask. Thanks in advance!
PS: Obligatory "English is not my native language, please excuse any spelling errors or gibberish"...
Okay, first I have to declare, that the coding style above and following are by any means not best practice.
While Sam Varshavchik is still right with how to learn C++ the right way, just changing
Process val = futureProcess[0].get();
to
static Process val = futureProcess[0].get();
did the job.
To be clear: don't do this. It's a quick fix but it will backfire in the future. But I hope that it'll help anyone with a similar problem.
If anyone has a better solution (it can't get any worse, can it?), feel free to add your answer to this question.

Why does Gplmpgdec (GPL MPEG-1/2 DirectShow Decoder Filter) override / detour IsDebuggerPresent?

In Mpeg2DecFilter.cpp the following code is present:
#include "detours.h"
DETOUR_TRAMPOLINE(BOOL WINAPI Real_IsDebuggerPresent(), IsDebuggerPresent);
BOOL WINAPI Mine_IsDebuggerPresent()
{
TRACE(_T("Oops, somebody was trying to be naughty! (called IsDebuggerPresent)\n"));
return FALSE;
}
...snip...
BOOL APIENTRY DllMain(HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
if(!fDetourInited)
{
DetourFunctionWithTrampoline((PBYTE)Real_IsDebuggerPresent, (PBYTE)Mine_IsDebuggerPresent);
...snip...
fDetourInited = true;
}
return DllEntryPoint((HINSTANCE)hModule, ul_reason_for_call, 0); // "DllMain" of the dshow baseclasses;
}
I can't for the life of me figure out why Gplmpgdec would override IsDebuggerPresent to always return FALSE. What possible use could this serve?
The thing is, for me it's causing problems due to debugger messages not showing up and (sometimes) the application crashing if a trace message gets written when the Gplmpgdec DLL has been unloaded.
In order to decide how to deal with this problem, I think I really need to know why Gplmpgdec is doing this. Any suggestions regarding a solution are also welcome. I'd rather not have to maintain my own custom Gplmpgdec library though; that kind of maintenance headache I'd rather avoid at all cost. Is there perhaps a way to disable the detour?
Some DirectShow filters actually don't work (on purpose) when a debugger is present.
I'm not sure if this is a workaround for that by Gplmpgdec or if it is related to the other hooked function; ChangeDisplaySettingsEx. You can clearly see references to Macrovision in the code which they probably try to disable.
Media Player Classic/MPC-HC uses the same type of code and it makes more sense in a .exe then in a decoder library.
I was also surprised to see this code in an open source project.
I think it is just a sort of joke from the developer. If you look the message
Oops, somebody was trying to be naughty!
for me it's second degree, and maybe the developer had just discovered IsDebuggerPresent, and found it fun to use it...
I also remember that at the time of this codec, some video codecs prevented the debugging of a DirectShow application (using filtergraph). Maybe this developer came from one of these companies...
to deal with this problem, you just have to comment this code, and recompile it.

C++ - a more efficient way to address a list inside loop argument

As title says. For example you have a list of values char values[11] and you want to cycle through that list inside the loop argument:
while(something not in values[])
{
doSomething(omgwtfbbq)
}
But of course it does not work in C++... or so I think. At least the 'not' keyword does not exist.
Can anyone suggest if there is a solvent for this?
You can use the way suggested by #Deepu but a cleaner and more robust solution would be to use events mechanism that exists in your system. On one thread you would wait for required-key-pressed event and on another you will intercept the key pressing interrupt and analyze the data. If it contains the required value(s), indicate the required-key-pressed event.
Ok, so the problem was solved, but the person who answered me in comments did not post a full reply, so I'll post the answer here.
Changed the list to a vector vector<char> values[4]. Then used the find function suggested by Raymond Chen:
while(find(values.begin(),values.end(),something)==values.end())
{
doSomething(eatBananas)
}
In case Raymond Chen posts an explicit answer, I'll mark his.

Windows 7 x64: low IL process msdn example does not work

I want to create process with low integrity level from process with medium integrity level.
I found msdn example: Designing Applications to Run at a Low Integrity Level
But it does not work on my system. Process is created successfully, but message box
"Alpplication failed to initialized properly(0xC0000022 -- STATUS_ACCESS_DENIED) ..."
is appeared. Did anybody meet the same problem?
I ran into this too. The SID used in the example is incorrect. It should be "S-1-16-4096", not "S-1-16-1024".
I have upvoted #dyared's answer because it helped me find the complete answer. I should mention first that I am not specialized in this matter and this is only a summary of my findings.
It seems that the MSDN example does not work with the specified SID string because it specifies an integrity level that is too low. From the Chromium's source code, the S-1-16-1024 SID used in the example is between INTEGRITY_LEVEL_BELOW_LOW and INTEGRITY_LEVEL_UNTRUSTED:
const wchar_t* GetIntegrityLevelString(IntegrityLevel integrity_level) {
switch (integrity_level) {
case INTEGRITY_LEVEL_SYSTEM:
return L"S-1-16-16384";
case INTEGRITY_LEVEL_HIGH:
return L"S-1-16-12288";
case INTEGRITY_LEVEL_MEDIUM:
return L"S-1-16-8192";
case INTEGRITY_LEVEL_MEDIUM_LOW:
return L"S-1-16-6144";
case INTEGRITY_LEVEL_LOW:
return L"S-1-16-4096";
case INTEGRITY_LEVEL_BELOW_LOW:
return L"S-1-16-2048";
case INTEGRITY_LEVEL_UNTRUSTED:
return L"S-1-16-0";
case INTEGRITY_LEVEL_LAST:
return NULL;
}
Furthermore, it seems that the SID S-1-16-4096, suggested by #dyared, is also used when launching Internet Explorer in protected mode, as claimed in Creating a Process in Protected Mode on Windows Vista article on MSDN Blogs.
However, because it was enough to get the example working does not mean it is strict enough for every situation and choosing the appropriate integrity level must be made understanding its implications.

CATIA-CAA CATKeyboardEvent

I know there are only a few CAA Programmers in the world but I try it anyway...
I can't get keyboard events to work. I found this code which looks reasonable but the Notification doesn't fire.
AddAnalyseNotificationCB(CATFrmLayout::GetCurrentLayout()->GetCurrentWindow()->GetViewer(),
CATKeyboardEvent::ClassName(),
(CATCommandMethod)&PROTrvTreeView::OnKeyboardEvent, NULL);
void PROTrvTreeView::OnKeyboardEvent(CATCommand * ipCmd, CATNotification * ipEvt, CATCommandClientData iobjData) {
cout<< "KeyboardEvent" <<endl;
}
Anyone any idea?
There is a much denser group of developers for CAA at:
http://www.3ds.com/alliances/c-java-developers/forum/
The same question came up, with several people mentioning that this API was unauthorized, and therefore you can't rely on it, even if it works.
The other samples there are essentially the same code as yours, but the only one that purports to work doesn't use CATKeyboardEvent::ClassName, but instead uses CATKeybdEvent. Might be worth a try.