Randomly strange behaviour when using select() with timeout on Windows - c#

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);

Related

Multithreaded server creates multiple threads by fails to read

I have been making a multithreaded server, I cant share much but I will tell in clear theory how it is working.
I have a server that goes in a while(true) loop and it waits for a connection. Everything works, it makes the multithreads. and the server does work when I read one at a time. However when I decide to run 10 threads, it returns and says it fails to read the message (in the cmd window).
Why is this or why could this be? I am also reading in the message by:
int characterNumer;
characterNumber = streamReader.read();
while(CharacterNumber > 0)
{
message += (char)CharacterNumber;
characterNumber = streamreader.read();
}
the second line is in a try catch statement twice so it does read. but for the server it fails. why is this?
What would you recommend or advise? It does work perfectly when it is not multithreading.

C# / GTK# Serial Port Read Issue

So I'm trying to read real time data from the serial port object in C# / Gtk#. I have a product which talks over RF to the computer and every time it gets a command it sends back an ACK. If I use AccessPort and auto send a command every 500ms, I get my ACK. I've ran AccessPort for hours and been able to match every single command to an ACK, so I know this is physically working.
I wrote a small program in C# / Gtk# that send data out the serial port at X ms and has a delegated thread which reads the serial port for any bytes that come back. My problem is that no matter how I write the method for the serial reading, it never actually captures all the bytes that I know are there.
So far this is the "lightest" code I have:
private void readSerial(){
byte readByte = 0x00;
Gtk.Application.Invoke (delegate {
try {
readByte = (byte)serialPort.ReadByte();
Console.WriteLine(readByte.ToString("X2"));
} catch (System.ArgumentException sae) {
Console.WriteLine(sae.Message);
}
});
}
I have assigned that method to a thread in the main function:
writeThread = new Thread (writeSerial);
readThread = new Thread (readSerial);
And I start it when a connect button is pressed, along with the writeThread. The writeThread is working fine as I can see the product execute the correct instruction every X ms ( currently I'm testing at 500ms). The ACK should arrive at the computer every X ms + 35 ms * module ID, so if my end product has a module id of 2 the response would be delayed by 70ms and hence the computer should see it at 570ms or X + 70ms.
Is there a better way to do this? I'm I doing something boneheadedly wrong?
Some other code I've played with was reading 0x0E bytes from the serial port and storing the bytes into a buffer, this also missed a lot of the bytes I know are coming back.
Can anyone offer some help? I do know the readSerial method is actually starting as I do see a 0x00 pop out on the console, which is correct as 0x00 are dispersed among the data I'm looking for.
Figured it out!
I'm not sure what the exact issue was but when I removed the delegation and just used a while(true) look inside that method it worked fine.

Tcl Channel in GUI Application

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.

Generating IntPtr using Convert.ToInt64 failing on x64 applications

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.

Keep alive code fails with new RDP client

For our Secure Terminal Server project, we have a need to keep the RDP session open, that is, to prevent the remote computer from timing out and locking the session. A little background:
We have several virtual servers configured as go-between agents, with a client piece that launches a RDP session to the virtual servers, and starts an application there. That application reads connection data from a database, including the username and password for connecting on to the final destination computer.
For remote desktop sessions, we use the ActiveX control extracted from MSTSCAX.DLL (using AxImp). Because the user does not have access to the password for the remote machine, we absolutely must keep the session from timing out.
For the past several months, we have been using the following code, triggered by a Timer object, to accomplish this. That worked great, until I had to upgrade the RDP client to version 6 in order to access Server 2008 boxes (we were using version 4 or 5, not sure which). Since then, the call to SendKeys will sometimes throw an HRESULT E_FAIL error -- often enough to cause major problems.
Does anyone have an idea as to what may be causing this? Better yet, does anyone have a better way to accomplish this that may work with the newer RDP client?
Thanks,
Dave
_mstscKeyControl = (IMsRdpClientNonScriptable)_mstsc.GetOcx();
private void KeepAlive()
{
try
{
if ( null != _mstsc && 0 != _mstsc.Connected )
{
bool[] bKeyUp = new bool[ 20 ];
int[] KeyData = new int[ 20 ]; // value matches lParam parameter of WM_DOWN message
/*
* Send CAPS LOCK on followed by OFF
*
* The SendKeys routine will not allow remote data in a single call to be mixed with
* local data so this shouldn't mess up anything.
*/
KeyData[ 0 ] = (int)MapVirtualKey( 14, 0 ); // vk_capital = CAPS LOCK
bKeyUp[ 0 ] = false;
KeyData[ 1 ] = KeyData[ 0 ];
bKeyUp[ 1 ] = true;
_mstscKeyControl.SendKeys( 2, ref bKeyUp[ 0 ], ref KeyData[ 0 ] );
}
}
catch ( Exception ex )
{
MessageBox.Show( ex.Message + Environment.NewLine + ex.StackTrace );
}
}
Instead of a sendkeys, is there a way to pass some kind of mousemove instead? I suspect this would be less invasive, if you only move the mouse a few pixels. I'm not sure if RDP has some kind of mouse movement threshold, though - maybe a few pixels isn't enough for it to reset the disconnect/lock timeout.
We'll eventually have this same problem (our terminal server is currently 2003, but we'll upgrade to 2008 at some point), so I'd really be interested to know what your solution ends up being.
I have the same need to keep RDP 6 alive from the client side. Came here via google, tried sendkey and mousemove, didn't work. Turn out WM_ACTIVATE do the trick.
Here's my basic AutoHotkey script segment:
SetTimer, RemoteMachine_Tick, 60000
RemoteMachine_Tick:
IfWinNotActive, remote01 - Remote Desktop
SendMessage, 0x006, 1, 0, , remote01 - Remote Desktop;
WM_ACTIVATE(0x006) WA_ACTIVE(1)
return
Have you tried managing Group Policies to configure Terminal Services and keep the session active?

Categories

Resources