I'm trying to use the code from the most popular answer to this question: Using C#, how does one figure out what process locked a file?
I'm testing this code in Windows 7 x64 using VS2010 and .NET v4.
I'm finding that the code excerpt...
var baTemp = new byte[nLength];
try
{
Marshal.Copy(ipTemp, baTemp, 0, nLength);
strObjectName = Marshal.PtrToStringUni(Is64Bits() ? new IntPtr(ipTemp.ToInt64()) : new IntPtr(ipTemp.ToInt32()));
}
catch (AccessViolationException)
{
return null;
}
finally
{
Marshal.FreeHGlobal(ipObjectName);
Win32API.CloseHandle(ipHandle);
}
is what is causing my problems. The Marshal.Copy can fail when the address created earlier is not valid. The code creating the address in x64 systems...
if (Is64Bits())
{
ipTemp = new IntPtr(Convert.ToInt64(objObjectName.Name.Buffer.ToString(), 10) >> 32);
}
in one instance of my noted failures starts with a buffer string representation of 20588995036390572032 that translates to x1C92AA2089E00000. The code appears to strip the low order word leaving x1C92AA20 as the usaable address.
Question 1: Why would we not simply use the 64bit address provided by the buffer object rather than shift out the low order word and use just the high order word in a 64bit app running on a 64bit OS?
Question 2: Should the try/catch/finally block include more than just AccessViolationException?
Read the comments on that article. Unworkable code. Doesn't work. Don't use. Even the "suggested" corrected version is broken (and it doesn't work on my Win8 64bits) and in the words of its author:
The following was produced based on Iain Ballard's code dump. It is broken: it will occasionally lock up when you retrieve the handle name. This code doesn't contain any work-arounds for that issue, and .NET leaves few options: Thread.Abort can no longer abort a thread that's currently in a native method.
Related
I am writing a .Net CE application on a Smart Device that has a printer on it. I collect my data in a StringBuilder object, and then try to print it. Here's how I print it
var receipt = new StringBuilder();
// ...
Printer.getInstance().print(receipt.ToString(), (int) Printer.TextAlign.Left, 0, 24, false);
Printer class is imported from a DLL. The application throws an unmanaged exception on the print line and crashes. But when I change my code to this
var receipt = new StringBuilder();
// ...
var str = receipt.ToString();
Printer.getInstance().print(str, (int) Printer.TextAlign.Left, 0, 24, false);
everything works fine. How is it even possible for the evalution of the StringBuilder affect the flow?
Here's a the methods from my Printer.dll (decompiled)
public int print(string text, int textAlign, int fontWeight, int fontSize, bool endLineFeed)
{
open();
Int32 prnReturn;
Printer.Prn_SetLang(1);
Printer.PRN_SetFont((byte) fontSize, (byte) fontSize, 0);
Printer.PRN_SetAlign(textAlign);
Printer.PRN_SetBold(fontWeight);
Prn_String(text.TrimEnd());
prnReturn = PRN_PrintAndWaitComplete();
if(endLineFeed)
printEndingLineFeed();
close();
return prnReturn;
}
public void open()
{
PRN_Open();
}
public void close()
{
PRN_Close();
}
private void printEndingLineFeed()
{
open();
//lineFeed(ENDING_LINE_FEED);
PRN_FeedLine(ENDING_LINE_FEED);
close();
}
and here are the methods that it calls from another DLL. Unfortunately, DotPeek doesn't decompile this.
[DllImport(PrinterDllName, SetLastError = true, EntryPoint = "PRN_FeedLine")]
public static extern Int32 PRN_FeedLine(Int32 pszData);
[DllImport(PrinterDllName, SetLastError = true, EntryPoint = "PRN_PrintAndWaitComplete")]
public static extern Int32 PRN_PrintAndWaitComplete();
Edit: Thanks to Kevin Gosse, I found out that the problem is only there in Debug mode. So my question now is, how does the debug mode evaluation differ from normal execution. Although I do understand that this might be off-topic, I'd be glad if someone could share a relevant piece of documentation.
In release mode, both versions of your code are identical.
In debug mode, there is a subtle difference as the lifetime of str will be extended until the end of the current method (for debugging purpose).
So this code in debug mode:
var receipt = new StringBuilder();
// ...
var str = receipt.ToString();
Printer.getInstance().print(str, (int) Printer.TextAlign.Left, 0, 24, false);
Is equivalent to this in release mode:
var receipt = new StringBuilder();
// ...
var str = receipt.ToString();
Printer.getInstance().print(str, (int) Printer.TextAlign.Left, 0, 24, false);
GC.KeepAlive(str);
When your string is given to the native code, it's not tracked by the GC anymore. Therefore, it could be collected which will cause errors in the native part.
In theory, the marshaller automatically protects you from such situations when using common types (such as string), as described here: https://learn.microsoft.com/en-us/dotnet/framework/interop/copying-and-pinning?redirectedfrom=MSDN. That's another puzzle, but it's possible that .net compact framework has a different marshaller and doesn't protect you automatically. Unfortunately it's hard to find specific documentation on the subject.
What surprised me when you decompiled the method is how the native call doesn't actually receive the original string but text.TrimEnd(). It means that the lifetime of the original value shouldn't have any impact (since the native code receives a different string). However, it turns out that .TrimEnd returns the original string when there's nothing to trim. When you added a space, it started crashing even with the version of the code that extends the lifetime of the string. That's because now you're extending the lifetime of the wrong string (since TrimEnd() will return a different instance, and that's the one that will be used by the native code).
I believe that the code working in Release is pure luck. Maybe it just changes the timing of the garbage collector and you don't run into that specific issue, but it could cause problems in the future. Out of caution, I would suggest you to:
Trim the string before calling Printer.getInstance().print
Call GC.KeepAlive on the trimmed string after the call to print
If you want to be extra safe, you can pin the string instead of calling GC.KeepAlive
I wish I could give more than theories, but I believe you're running into specificities of .net compact framework. If somebody with more experience on the subject reads this and could give more information, that would be much appreciated.
I'm using a tool to communicate with a gameserver. To establish the connection with the gameserver I'm sending a login packet and then go on from there. I also used a tool, that does the same, but which is written by someone else in C# with a pre-made library. This app has some issues with stackoverflow exceptions after using it for hours and porting it linux isn't much fun aswell, therefore I decided to write my own application from scratch in C++.
My script pretty much looks like this:
while (!connected) {
if (connectCounter == 0)
std::cout << "Trying to connect..." << std::flush;
else
std::cout << "." << std::flush; // add point
connectCounter++;
int selectSize = 0;
struct timeval timeout;
timeout.tv_sec = 5;
timeout.tv_usec = 0;
fd_set fds;
FD_ZERO(&fds);
FD_SET(mysocket, &fds);
selectSize = select(mysocket + 1, &fds, 0, 0, &timeout);
if (selectSize == 1) {
// we might now be logged in, check routines
connected = true;
}
}
Now there's a "bug" randomly happening to me in both applications, the one written by someone else in C# and in my own one. I should probably mention that I've never had this behaviour before, but sinced I formatted my computer I saw this issue happpening for the first time.
Issue: Gameserver was offline for some hours, computer was probably freshly booted. Gameserver is still down and I start the application. Now it tries to login but won't have success as the gameserver is still offline. Now it writes "Trying to connect". Because of the timeout settings it should wait 5 seconds and then add 1 point after every unsuccessful try. Instead it fires point after point without waiting for the timeout. This happens in both application, the C# app written by someone else and in my own application. In both applications it only happens randomly and not every time I'm starting the application. As I mentioned I've never experienced this issues before formatting my computer. I also ported this application to my linux server and didn't not experience that behaviour on linux. A friend of mine also uses both applications and never reported that kind of issue to me.
This is so strange to me and I can't figure out the reason for it. From what I get this can't really be code related because it happens in two totally different applications and from what I can tell only since I reinstalled Windows.
EDIT 1: Now I found something interesting, I added the following code on windows and linux:
selectSize = select(mysocket + 1, &fds, 0, 0, &timeout);
std::cout << selectSize << std::cout;
Interesting thing is that on Windows my console will now output: Trying to connect...0.1.0.1.0.1.0.1
Restarted the application and it outputs Trying to connect...0.0.0.0.0.1
On linux it always returns Trying to connect...0.0.0.0.0, never ever with a false positive.
Still only happening on windows. Don't even know what approach the guy from the C# application used but there it's the same problem happening randomly after reinstalling windows.
EDIT 2: I guess I found the problem.
Before the timeout settings and select() I'm doing a sendto() with my login packet. I guess for whatever reason there is something incoming in return, so that selectSize might change to 1 in some cases. Is it possible that this is causing the issue on Windows, while its working on linux?
Quoting from "the" POSIX specification (a copy of it online):
A descriptor shall be considered ready for reading when a call to an input function with O_NONBLOCK clear would not block, whether or not the function would transfer data successfully. (The function might return data, an end-of-file indication, or an error other than one indicating that it is blocked, and in each of these cases the descriptor shall be considered ready for reading.)
So I'd say in order to fix your code you must additionally check whether file descriptors that are "ready for reading" don't have any error or eof indication.
To check if the socket is connected, you should check it for writability, not readability. Change
selectSize = select(mysocket + 1, &fds, 0, 0, &timeout);
to
selectSize = select(mysocket + 1, 0, &fds, 0, &timeout);
Okay, so it seems that I finally found at least a partial answer to my initial question, why linux gives me a working result while windows breaks my application. From what I have read on windows platforms select() returns WSAECONNECTRESET instead of blocking or timeout, see: WinSock Recvfrom() now returns WSAECONNRESET instead of blocking or timing out
So this seems to be the reason why the application is working perfectly fine (for my purposes) on linux, where select() still seems to return a timeout while Windows returns that error and breaks my application to a certain extent.
Solution:
So I finally found a fix. Special thanks to the guy who reminded me to use Wireshark. At first I tought the select() giving back 1 when it should be 0 after sending the login packet to gameserver while it's offline is totally random but in fact I found out that from time to time I get a "ICMP port unreachable", this caused select() to return 1 instead of 0 (see the link above) Obviously I only want select() to return 1 when an actual login reponse is coming from the sever. On linux this works out of the box and doesn't cause any problems.
For Windows I found a simple fix by adding this code before the select() function:
#define SIO_UDP_CONNRESET _WSAIOW(IOC_VENDOR, 12)
DWORD lpcbBytesReturned = 0;
BOOL lpvInBuffer = FALSE;
WSAIoctl(mysocket, SIO_UDP_CONNRESET, &lpvInBuffer, sizeof(lpvInBuffer), NULL, 0, &lpcbBytesReturned, NULL, NULL);
Ive been working on some communication between a PC and a Raspberry PI 2 with Windows 10 IoT (build 10586 TH2) using "StreamSocketListener". This seems to work fine in debug mode, but when testing the code in release mode the "StreamSocketListener" seems to randomly stop responding to requests.
In debug mode, on the RPI2, I've had sessions with 100k requests without a single issue, but when I push the release build it stops, randomly, quite quickly (typically after a couple of hundreds requests). The request is of static type, so the input is the same every time.
Has anyone experienced the same issue, and is there a solution to this problem?
The code is based on this blog post:
A simple in-process HTTP server for Windows 8 Metro apps
private void Listen()
{
_listener = new StreamSocketListener();
_listener.ConnectionReceived += (s, e) => ProcessRequestAsync(e.Socket);
_listener.BindServiceNameAsync(requestPort.ToString());
}
private async void ProcessRequestAsync(StreamSocket socket)
{
try
{
// this works for text only
StringBuilder request = new StringBuilder();
using (IInputStream input = socket.InputStream)
{
byte[] data = new byte[BufferSize];
IBuffer buffer = data.AsBuffer();
uint dataRead = BufferSize;
while (dataRead == BufferSize)
{
await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
request.Append(Encoding.UTF8.GetString(data, 0, data.Length));
dataRead = buffer.Length;
}
}
using (IOutputStream output = socket.OutputStream)
{
string requestMethod = request.ToString().Split('\n')[0];
string[] requestParts = requestMethod.Split(' ');
if (requestParts[0] == "GET")
await WriteResponseAsync(requestParts[1], output);
else
throw new InvalidDataException("HTTP method not supported: "
+ requestParts[0]);
}
}
catch (Exception e)
{
Debug.WriteLine("Main ex: " + e);
}
RequestCount++;
}
After a whole day long term testing with the "Compile with .NET Native tool chain" setting turned ON for my UWP project this issue seems to be fixed. When disabling this feature the issue occur after just a couple of minutes.
Because I cant accept a comment as an answer, I'll just answer my own question, and accept it. But all thanks to Matt for pointing me in the right direction.
Interesting... does this still reproduce if you disable .NET Native compilation? (Project properties > BUILD > "Enable .NET Native toolchain") – Matt Whilden
Matt, Gnm:
I've had exactly the same issue on a RPi3 running on Win-IoT 10.0.14393.693, with a C# code very similar to that in Gnm's first post: StreamSocketListener just stopping to listen to/receive http POST messages while the rest of the app (a web server background service) remained responsive.
Two differences though:
a) on my machine, that happened already within one minute after app launch, and after only one or two requests.
b) And it happened with the "Compile with .NET Native Tool chain" option switched to "ON"!
Inspired by Gnm's findings I have now switched this option to OFF, and: my problem appears to be solved. At the time of writing this, the code has been running for one hour only, but it appears to be working and stable now. So, surprisingly, for me the exact opposite of Gnm's solution works...
FYI I had the same problem for a Windows 10 Iot c# app. Mine was fixed by "Compile with .NET Native Tool chain" option switched to "ON" then "Compile with .NET Native Tool chain" option switched to "OFF"!
Application/Code description:
My application is based on c# and uses SQL Server CE and iv'e got this exception only twice at the same code location. the crash with this exception was not introduced till this version. the only change in this version was changing the .net framework to 4.5.2.
I'm getting access violation exception on the dispose of an SqlCeConnection with the following error:
Attempted to read or write protected memory. This is often an
indication that other memory is corrupt.
This exception is not intercepted by the try catch clause of .net- it causes a crash.
In my code I use the following to run
try
{
var connectionString = string.Format("{0}{1}{2}", "Data Source=", _localDB, ";File Mode=Read Write;Max Database Size=4000;Persist Security Info=False;");
using (var sqlCeConnection = new SqlCeConnection(connectionString))
{
using (var sqlCeCommand = new SqlCeCommand())
{
sqlCeCommand.Connection = sqlCeConnection;
sqlCeCommand.CommandText = "SELECT * FROM Application";
sqlCeConnection.Open();
var result = (string)sqlCeCommand.ExecuteScalar();
isValid = !IsValid(result);
}
}
}
catch (Exception ex)
{
_log.Error("exception", ex);
}
call stack for the first crash:
ntdll!ZwWaitForMultipleObjects+a
KERNELBASE!WaitForMultipleObjectsEx+e8
kernel32!WaitForMultipleObjectsExImplementation+b3
kernel32!WerpReportFaultInternal+215
kernel32!WerpReportFault+77
kernel32!BasepReportFault+1f
kernel32!UnhandledExceptionFilter+1fc
ntdll! ?? ::FNODOBFM::`string'+2365
ntdll!_C_specific_handler+8c
ntdll!RtlpExecuteHandlerForException+d
ntdll!RtlDispatchException+45a
ntdll!KiUserExceptionDispatcher+2e
sqlcese35!__SafeRelease+c
sqlcese35!Column::`vector deleting destructor'+5c
sqlcese35!Object::DeleteObjects+39
sqlcese35!Table::`vector deleting destructor'+45
sqlcese35!Table::Release+27
sqlcese35!HashTable::~HashTable+2a
sqlcese35!Store::~Store+12b
sqlcese35!Store::Release+2a
sqlceme35!ME_SafeRelease+17
DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr ByRef)+78
[[InlinedCallFrame] (System.Data.SqlServerCe.NativeMethods.SafeRelease)] System.Data.SqlServerCe.NativeMethods.SafeRelease(IntPtrByRef)
System.Data.SqlServerCe.SqlCeConnection.ReleaseNativeInterfaces()+147
System.Data.SqlServerCe.SqlCeConnection.Dispose(Boolean)+f1
System_ni!System.ComponentModel.Component.Dispose()+18
call stack for the second crash:
ntdll!NtWaitForMultipleObjects+a
KERNELBASE!WaitForMultipleObjectsEx+e8
kernel32!WaitForMultipleObjectsExImplementation+b3
kernel32!WerpReportFaultInternal+215
kernel32!WerpReportFault+77
kernel32!BasepReportFault+1f
kernel32!UnhandledExceptionFilter+1fc
ntdll! ?? ::FNODOBFM::`string'+2335
ntdll!_C_specific_handler+8c
ntdll!RtlpExecuteHandlerForException+d
ntdll!RtlDispatchException+45a
ntdll!KiUserExceptionDispatcher+2e
<Unloaded_sqlcese35.dll>+7c88c
<Unloaded_sqlceqp35.dll>+102790
0x06ccc898
0x06f9efc8
0x1eca8018
0x1f207400
<Unloaded_sqlcese35.dll>+228dc
0x00000004
0x2edff008
0x00000002
0x00000003
0x00000004
<Unloaded_sqlcese35.dll>+3fbd9
0x06ccc898
DomainBoundILStubClass.IL_STUB_PInvoke(IntPtr ByRef)+78
[[InlinedCallFrame] (System.Data.SqlServerCe.NativeMethods.SafeRelease)] System.Data.SqlServerCe.NativeMethods.SafeRelease(IntPtrByRef)
System.Data.SqlServerCe.SqlCeConnection.ReleaseNativeInterfaces()+147
System.Data.SqlServerCe.SqlCeConnection.Dispose(Boolean)+f1
System_ni!System.ComponentModel.Component.Dispose()+1b
I found some references on the internet that suggests some solutions:
Probable solution: check multithreading issue on the same connection (attempted to read write protected memory. this is often an indication that other memory is corrupt)
Rejection:
a. the connection is created in the using brackets and doesn't get reused.
b. the calling method is called every 5 minutes and verified via the dump file that it was not called simultaneously.
Probable solution: sql ce version mismatch (http://blogs.msdn.com/b/sqlservercompact/archive/2009/05/06/troubleshooting-access-violation-exception-while-using-sql-server-compact-database-with-ado-net-provider.aspx)
Probable Rejection: I can see in the version installed is 3.5 SP2 (3.5.8080.0) and from the modules located in the dump I can see the sqlceme35.dll, System.Data.SqlServerCe.dll DLL's are with version 3.05.8080.0
Probable solution which is in question is the following:
https://stackoverflow.com/a/20492181/1447518
Probable Rejection: it doesn't sound right from a statistical perspective- the code crashed twice in the same place although there another place in the application code which writes and read to a different DB and the application didn't crash there.
The last thing I was thinking about, may suggest a unload problem of DLLs (take a look at the second call stack). My guess is that the dll's are unloaded from the application while the application needed them in order to do a dispose, but it seams a bit blurry and a 'long shot'
My question is: what may cause the problem, and what is a probable solution?
Although this solution is not yet verified, the solution is as follows:
From the second call stack i can see there is unload of native DLL's, my guess was that the dispose method of the SQL connection was using one of the methods it currently disposed.
I verified thorough the Process dump that all the SqlCeConnection types were in the process of dispose.
Seeing ErikEj comment made me realize it's will be better if i will take a look in the code differences that was made between SQL-CE 3.5 to 4.0 (System.Data.SqlServerCe.dll).
after viewing the code, i could see that the method of the release was moved to a later position inside the dispose method.
In addition i could see that before calling SafeRelease there was another check that checks if the native DLLs that were needed for safe release was released already- and throw an exception.
bottom line, SQL-CE 4.0 has 2 solutions for the same issue.
my guess is that this issue was caused because of this.
the solution for now was to keep a connection during all the application life-cycle (which has no connection string), this cause the pointer pool to keep the native Dlls in the memory for all the application life-cycle.
the better solution is to move to SQL-CE 4.0 .
Im trying to embedded Tcl interpreter to C# GUI application, and everything works fine,
even AttachingNewFunction to TclCommand.
But one thing is to hard for me,
I want to redirect
stdout, stdin, stderr
to some TextBox'es.
Im working now with C++, becouse its easier to debug and compile.
so i using code
Tcl_Channel StdOut = Tcl_GetStdChannel(TCL_STDOUT);
Tcl_UnregisterChannel(interp,StdOut);
Tcl_Channel myStdOut = Tcl_CreateChannel(typePtr, "stdout",
NULL, TCL_READABLE | TCL_WRITABLE);
Tcl_RegisterChannel(interp, myStdOut);
Tcl_SetStdChannel(myStdOut, TCL_STDOUT);
to register new stdout,
typePtr look like
typePtr->typeName = "stdout";
typePtr->version = TCL_CHANNEL_VERSION_2;
typePtr->getHandleProc = Tcl_MyDriverGetHandleProc;
typePtr->inputProc = Tcl_MyDriverInputProc;
typePtr->outputProc = Tcl_MyDriverOutputProc;
typePtr->flushProc = Tcl_MyDriverFlushProc;
typePtr->watchProc = Tcl_MyDriverWatchProc;
typePtr->closeProc = Tcl_MyDriverCloseProc;
typePtr->blockModeProc = Tcl_MyDriverBlockModeProc;
typePtr->seekProc = NULL;
typePtr->close2Proc = NULL;
typePtr->handlerProc = NULL;
typePtr->wideSeekProc = NULL;
typePtr->truncateProc = NULL;
typePtr->setOptionProc = NULL;
typePtr->getOptionProc = NULL;
typePtr->threadActionProc = NULL;
and every function which i connect return TCL_OK or EINVAL (i know it from API)
and puts some text to file, example
int Tcl_MyDriverCloseProc(ClientData instanceData,
Tcl_Interp *interp) {
std::cout << "\n Tcl_MyDriverCloseProc\n";
file << "\n Tcl_MyDriverCloseProc\n";
file.flush();
return EINVAL;
}
i also use std::cout to debugging, but i dont believe him.
When i compile&run nothing happen, stdout doesnt work, the result is for example
result:stderr file8adcd0 stdout stdin:
result::
the code what i compiled is
Tcl_GetChannelNames(interp);
std::cout << "result:" << Tcl_GetStringResult(interp) << ":\n";
Tcl_Eval(interp, "puts SomeOneHelp");
std::cout << "result:" << Tcl_GetStringResult(interp) << ":\n";
I also cannot create custom channel and used it like
"puts myChannel pleHdeeNI"
when i done with C++ im going to make function in C# which will be writing 3 TCL standart channels into TextBox'es, but its easy.
The documentation of the low level of Tcl channels isn't the easiest, so it is probably instructive to look at example code. generic/tkConsole.c in Tk's implementation shows how the real stdout and stderr redirections are done. In particular, the fields that need non-NULL values are the name, version, closeProc (or close2Proc), inputProc, outputProc, watchProc and getHandleProc, and many of those can actually be dummies for the channels you create to handle stdout and stderr.
However, the Tk console widget doesn't support actually providing a real stdin (instead, it uses Tcl_Eval to run commands in the main interpreter) and the one it provides just claims to always be at end-of-file. It's a bit of a cop-out. Also, none of the channels are at all able to be passed to subprocesses as they don't have any representation at the level of the OS. Fixing that would require enormously more work (perhaps with anonymous pipes and worker threads and tricks to deal with the inevitable buffering issues; using something like the Expect package would do a much more complete job, though at a cost of even more complexity).
You probably want to return non-error results from things. For example, always returning 0 from your outputProc will cause great problems with the generic parts of Tcl's channel code; it assumes that this means that things are blocked and just buffers things up until it gets told that they have become unblocked. For a real swallow-everything first try, return the number of bytes written as the same as the number of bytes you were asked to write. Similarly, it is also important to make the closeProc work right; if you've no instance data to dispose of or underlying OS resources to get rid of, you can just return 0 there to indicate that everything is OK.