could stl set::insert cause BSOD? - c++

I have written a 'filemon' utility which basically logs file being opened during a period of time. Now I have exact these two functions in my 'filemon' utility:
set<wstring> wstrSet;
// callback - get notified by callback filter driver on any file open operation
void CbFltOpenFileN(
CallbackFilter* Sender,
LPWSTR FileName,
ACCESS_MASK DesiredAccess,
WORD FileAttributes,
WORD ShareMode,
DWORD CreateOptions,
WORD CreateDisposition )
{
// don't log for directories
if (FileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
return;
}
wstring wstr = FileName;
wstr.append(L"\n");
//wstrSet.insert(wstr); // as soon as I un-comment this line I start getting BSOD in multiple execution of this utility
}
// Read all paths stored in the set and write them into the log file
void WritePathsToLog() {
typedef set<wstring>::const_iterator CI;
printf("\nNo. of files touched ===> %d\n\n", wstrSet.size());
for (CI iter = wstrSet.begin(); iter != wstrSet.end(); iter++) {
fputws((*iter).c_str(), logFile);
}
}
Basically what this code does is that 'filemon' utility interacts with callback filter driver and whenever file is touched by any process the driver reports the respective filename to the 'filemon' utility via CbFltOpenFileN function.
Now the issue is that this 'filemon' utility runs fine on win7 x64 machine 4GB machine but as soon as I uncomment the last line in the CbFltOpenFileN function i.e. start inserting the reported filename in the set then I start getting BSOD mostly with BugCheck 0xCC and sometimes with BugCheck 0x50 which basically indicates that "system is trying to access already freed memory"
P.S. on win7 x64 with 8GB RAM I am not seeing any issue at all irrespective of whether last line in the CbFltOpenFileN function is commented or not.
Currently, 'wstrSet' is using default allocator so do I need to use a specific allocator while declaring set wstrSet; if yes can someone tell me how & why?
Let me share some more information here:
I am using VS2010
My utility is a 32 bit application targeted for x86 platform
The fileystem filter driver I am using is callabck filter driver provided by Eldos corp.
Now I am tetsing this utility using a simulator which generates lots of files and then starts the 'filemon' utility, then it touches all those files and at the end stops the 'filemon' utility. This simulator repeates this process 25 times.
Now for case where last line is commented I get empty log file created 25 times as I don't insert anything in set but 'filemon' utility also doesn't causes any BSOD
But for case where last line is NOT commented I get log file created each time with path enteries as now I am inserting paths in the set but then during first few iteration, say 2nd or 3rd or 6th, itself 'filemon' utility hits this BSOD scenario.
It's hard for me to repro this issue in debug mode as my simulator take cares of the start/stop of 'filemon' utility and i need to run it multiple time to repro the issue.
Hope this added info helps!!!
Thanks and Regards,
Sachin

If you CbFltOpenFileN is a callback function, does this means it has asynchron calls? in that case, you might want to protect the global variable (wstrSet) with a mutex...

Related

reading (not writing) last_write_time gives a file creation error

I'm stumped... it took me a while to track this down.. because I don't have visual C++ IDE installed on the problematic system (it is windows server 2019)... my code works fine with VS 2022 on my laptop (W11 22H2)... anyhow.. I get this exception
Cannot create a file when that file already exists
I tracked it down to this code:
const auto fileTime = fs::last_write_time(p);
apparently this function can also write to the file to modify the time.
but I'm just trying to read it... (I didn't add the arguments necessary to write)
does anyone have any idea why this error might be happening?
https://en.cppreference.com/w/cpp/filesystem/last_write_time
please note it is highly likely that sometimes the file is actually being written to when I call this code (this code is called in a loop, and so is the file that is being written by another program)

Deleted file still reported as existing (Windows only)

(Note that this is not primarily a Qt question)
It seems to me that the return value of QFile::exists() is sometimes incorrect.
Consider the following two unit-test-like snippets (each of which I have executed a few thousand times in a loop)
// create file
QFile file("test.tmp");
QVERIFY(file.open(QIODevice::WriteOnly));
QVERIFY(file.write("some data") != -1);
file.close();
// delete file
QVERIFY(file.remove());
// assert file is gone
QVERIFY(!file.exists()); // <-- 5..10 % chance of failure
and
// create file
QFile file("test.tmp");
QVERIFY(file.open(QIODevice::WriteOnly));
QVERIFY(file.write("some data") != -1);
file.close();
// delete file
QVERIFY(file.remove());
// retry until file is gone (or until timeout)
for (auto i = 0; i < 10; i++)
{
if (!file.exists()) // <-- note that only the check is retried, not the actual delete
return;
QThread::yieldCurrentThread();
}
QFAIL("file is still reported as existing"); // <-- never reached in my tests
The first unit test fails about 8 out of 100 times. Always on the last line of code (indicating that the file still exists). The second unit test never fails.
This behavior was observed on a Windows 10 system using NTFS (with Qt 5.2.1). It could not be reproduced using ubuntu 16.04 LTS using ext4 on a VM (with Qt 5.8.0)
Not sure if this helps:
Process Monitor (when it succeeds)
Process Monitor (when it fails)
So my questions are:
what is happening?
what are implications that I might be interested in?
update:
For clarification: I am hoping for an answer like "this is caused by the NTFS feature 'bills-fancy-caching-magic'". From there I would like to find out, whether Qt does look over this feature intentionally.
According to the Windows API documentation, it is defined behaviour:
The DeleteFile function marks a file for deletion on close. Therefore, the file deletion does not occur until the last handle to the file is closed. Subsequent calls to CreateFile to open the file fail with ERROR_ACCESS_DENIED.
It seems to be a property of the Windows kernel and therefore not to be limited to NTFS.
The behaviour seems to be unpredictable, as other services (think virus scanners) might open the file in question.

redhawk module service function usage example crashes

So I am building a redhawk module and trying to just pass data through it as a test. After putting their example of how to work with input and output ports into the serviceFunction() I am able to build the module with no errors (I changed variable names to match my ports). When I put the module on the white board and link it up it's fine but as soon as I start the module it crashes. I added a line to write the incoming stream id to the console and that will hit the console 10 to 20 times before the crash (it correctly writes the id of the signal generator that is providing the signal). If I plot the output port nothing is plotted before the crash (when I say crash I mean that the module just disappears from the white board, the ide is still up and running).
The service function is:
int freqModFrTest_i::serviceFunction()
{
bulkio::InFloatPort::dataTransfer *tmp = dataFloatIn->getPacket(bulkio::Const::BLOCKING);
if (not tmp) { // No data is available
return NOOP;
}
else
{
std::cout<<tmp->streamID<<std::endl;
std::vector<float> outputData;
outputData.resize(tmp->dataBuffer.size());
for (unsigned int i=0; i<tmp->dataBuffer.size(); i++) {
outputData[i] = (float)tmp->dataBuffer[i];
}
// NOTE: You must make at least one valid pushSRI call
if (tmp->sriChanged) {
ComplexOut->pushSRI(tmp->SRI);
}
ComplexOut->pushPacket(outputData, tmp->T, tmp->EOS, tmp->streamID);
delete tmp; // IMPORTANT: MUST RELEASE THE RECEIVED DATA BLOCK
return NORMAL;
}
}
Has anyone had a similar issue or any ideas on what would be causing this?
Additional Info:
Following the sugestion by pwolfram I built a sig generator and this component into a waveform. When launching it from a domain I got the error:
2016-01-14 07:41:50,430 ERROR DCE:aa1a189e-0b5b-4968-9150-5fc3d501dadc{1}:1030 -
Child process 3772 terminated with signal 11
when trying to restart the component (as it just stoped rather then disapering) I get the following error:
Error while executing callable. Caused by org.omg.CORBA.TRANSIENT:
Retries exceeded, couldn't reconnect to 10.62.7.21:56857
Retries exceeded, couldn't reconnect to 10.62.7.21:56857
In REDHAWK 2.0.0 I created a component with the same name (freqModFrTest) and port names (dataFloatIn and ComplexOut) and used your service function verbatim. I did not however get any issues.
Here are a few things to try:
Clean and rebuild the component. The Sandbox (what you referred to as the whiteboard) will run the binary that has been built. It is possible that you've modified the code and have an older version of the binary on disk. Right click on the project and select "clean project". Then right click and select "Build Project" this will make sure that the binary matches your source code.
Run the component in debug mode. If you double click on the SPD file, under the "overview" tab there is "Debug a component in the sandbox". This will launch the component in the chalkboard within a debugging context. You can set breakpoints and walk through the code line by line. If you set no breakpoints though the IDE will stop execution when a fatal error occurs. If there is an issue (like invalid memory access) the IDE will prompt you to enter debug mode and it should point out the line in code where the issue is.
If those options fail, you can enable core dumps and use GDB to see where in the code the issue is occurring. There are lots of tutorials online for GDB but the gist is that before launching the IDE, you'll want to type "ulimit -c unlimited" then from the same terminal, launch the IDE. Now when your component dies, it will produce a core file.
Hopefully one of these gets you going down the right path.

Using "rundll32.exe" to access SpeechUX.dll

Good Day,
I have searched the Internet tirelessly trying to find an example of how to start Windows Speech Training from with in my VB.Net Speech Recognition Application.
I have found a couple examples, which I can not get working to save my life.
One such example is on the Visual Studios Fourms:
HERE
this particular example users the "Process.Start" call to try and start the Speech Training Session. However this does not work for me. Here is the exmaple from that thread:
Process.Start("rundll32.exe", "C:\Windows\system32\speech\speechux\SpeechUX.dll, RunWizard UserTraining")
What happens is I get and error that says:
There was a problem starting
C:\Windows\system32\speech\speechux\SpeechUX.dll
The specified module could not be found
So I tried creating a shortcut (.lnk) file and thought I could access the DLL this way. My short cut kind of does the same thing. In the short cut I call the "rundll32.exe" with parameters:
C:\Windows\System32\rundll32.exe "C:\Windows\system32\speech\speechux\SpeechUX.dll" RunWizard UserTraining
Then in my VB.Net application I use the "Process.Start" and try to run the shortcut.
This also gives me the same error. However the shortcut itself will start the SPeech Training session. Weird?!?
So, I then took it one step further, to see if it has something to do with my VB.Net Application and the "Process.Start" Call.
I created a VBScript, and using "Wscript.Shell" I point to the Shortcut.
Running the VBScript calls the Shortcut and low and behold the Speech Training starts!
Great! But...
when I try to run the VBscript from my VB.net Application, I get that error again.
What the heck is going on here?
Your problem likely is that your program is compiled as 32-bit and your OS is 64-bit, and thus, when you try to access "C:\Windows\System32\Speech\SpeechUX\SpeechUX.dll" from your program, you're really accessing "C:\Windows\SysWOW64\Speech\SpeechUX\SpeechUX.dll" which, as rundll32.exe is reporting doesn't exist.
Compile your program as 64-bit instead or try the pseudo directory %SystemRoot%\sysnative.
Also, instead of rundll32.exe, you may want to just run SpeechUXWiz.exe with an argument.
Eg.
private Process StartSpeechMicrophoneTraining()
{
Process process = new Process();
process.StartInfo.FileName = System.IO.Path.Combine(Environment.SystemDirectory, "speech\\speechux\\SpeechUXWiz.exe");
process.StartInfo.Arguments = "MicTraining";
process.Start();
return process;
}
private Process StartSpeechUserTraining()
{
Process process = new Process();
process.StartInfo.FileName = System.IO.Path.Combine(Environment.SystemDirectory, "speech\\speechux\\SpeechUXWiz.exe");
process.StartInfo.Arguments = "UserTraining";
process.Start();
return process;
}
Hope that helps.
Read more about Windows 32-bit on Windows 64-bit at http://en.wikipedia.org/wiki/WoW64
or your problem specifically at http://en.wikipedia.org/wiki/WoW64#Registry_and_file_system
If you are using a 64bit OS and want to access system32 folder you must use the directory alias name, which is "sysnative".
"C:\windows\sysnative" will allow you access to system32 folder and all it's contents.
Honestly, who decided this at Microsoft is just silly!!

First call to Windows Performance Counters (PDH) sometimes fails

I'm having a problem where sometimes my code will function correctly, but other times it will fail.
This is the first bit of PDH related code that I run:
const std::wstring pidWildcardPath = L"\\Process(*)\\ID Process";
DWORD bufferSize = 0;
LPTSTR paths = NULL;
PDH_STATUS status = PdhExpandCounterPath(
pidWildcardPath.c_str(),
paths,
&bufferSize);
checkPDHStatus(status, PDH_MORE_DATA, L"Expected request for more data.");
The result of the PdhExpandCounterPath function call is 0x800007D0 (PDH_CSTATUS_NO_MACHINE). The checkPDHStatus function is a simple function that I wrote that asserts that the status is equal to the second parameter. In this case, I expect the result to be PDH_MORE_DATA because paths is NULL and bufferSize is 0. The goal of this call is to determine the size of the buffer I must allocate to store all of the results for a subsequent call to PdhExpandCounterPath. This is described in the PDH documentation under the Remarks section.
The list of PDH error codes describes PDH_MORE_DATA as "Unable to connect to the specified computer, or the computer is offline." As you can see by the performance counter path in the code above, I am not even trying to connect to a different computer than my own.
It is interesting the way that this code fails. Sometimes it works fine and then other times, it will fail on multiple back-to-back executions of my application. I have #include <pdh.h> in my header file and I have a section in my property sheet for this DLL that looks like this:
<Tool
Name="VCLinkerTool"
AdditionalDependencies="pdh.lib"
/>
I'm not sure if it matters, but this program is built by Visual Studio 2005 and run on Windows XP. Am I doing something incorrectly?
I'm a co-worker of Dave's and have discovered the following during my investigation:
the code above runs fine when run from a logged-in interactive session
the code runs fine when initiated as a Scheduled Task AND the user is logged in at the time the scheduled task is fired off
the code FAILS only when run as a Scheduled Task AND the user is NOT logged in at the time the task starts
the code continues to fail if the user logs in after the failing task has started but while it is still running (because it is looping "endlessly" until it gets a PDH_MORE_DATA status back).
In the failing instances, the following environment variables have not been established/set for the program: APPDATA, HOMEDRIVE and HOMEPATH ... I don't think this is a problem. However, the failing program also lacks the SeCreateGlobalPrivilege from its token; the passing programs all have this privilege in the token and PERFMON shows it as "Default Enabled". The other difference is that failing program has the NT_AUTH\BATCH user group in the token, while the passing program has NT_AUTH\INTERACTIVE instead ... all other user groups and privileges are the same for both cases. I think the global privilege is coming from the interactive login, but don't know if it has any bearing on PDH operation.
I cannot find anything in the Performance Counter/PDH documentation that talks about needing any special permissions or privileges for this functionality to succeed. Is the global privilege required to use Performance Counters ?
Or is there some other context/environment difference between running Scheduled Tasks (as a specific user) when that user is/isn't logged in at the time the task starts, that would account for the PDH call succeeding/failing respectively ?
Try this format, indicating the local computer:
const std::wstring pidWildcardPath = L"\\.\Process(*)\ID Process";