I have a C# application that uses D-Link GSM Modem to send/receive SMS messages.
Now for some reason the D-Link USB gets disconnected and reconnected automatically after some time (random). When it re-connects it opens up the D-Link Connection Manager which reserves the COM4.
Now when my application run and tries to send SMS it fails, because it doesn't find any available (already in use my D-Link Manager).
when i tried as at application load if the D-Link Process is there I'm killing it using process.kill(). That kills the application but still the COM4 remains inaccessible.
Is there a way to kill the process and release the COM port also programmatically ?
Killing a process doesn't give it a chance to clean up. It is easy for COM ports to get hung up if clients terminate abnormally.
Try Process.CloseMainWindow. Hopefully, the process will respond by shutting down normally and closing the COM port. You would have to give it some time to shut down, though, for which you could use Process.WaitForExit.
The SerialPort class implements IDisposable for exactly this reason: to clean up unmanaged resources (like the port itself) when the port variable goes out of scope.
using (var serialPort = new SerialPort())
{
// Set the read/write timeouts
serialPort.ReadTimeout = 500;
serialPort.WriteTimeout = 500;
serialPort.Open();
// do something
}
It won't always get cleaned up when you kill the process, but this way, you're giving it a fighting chance.
one should blame poorly designed operating system for not being capable to clean the resources of the process after killing it
Related
Background
On Linux or BSD, it is possible to send handles to open files or sockets between unrelated processes with SCM_RIGHTS, and I have this working, such that on process is listening for connections, and then forwards the handles to a process that performs the communication.
Problem
I am unable to figure out how to free the socket handle from the listening process without shutting down the socket.
There are two conflicting descriptions in man close(3):
When all file descriptors associated with an open file description have been closed, the open file description shall be freed.
And
If fildes refers to a socket, close() shall cause the socket to be destroyed.
I originally thought that this means that calling close() will just decrement the reference count for the kernel object that has the socket, such that the last description from man close(3) meant "destroy when the last descriptor is closed".
EDIT: This is how it is supposed to work, and also how it works.
But, when I run tests, it appears that as soon as I call close() on the socket descriptor in the listening process, it will start closing the socket, sending either RST or FIN, depending on what the other process is doing with the socket at the time.
One solution would be to have a callback from the handing process with "you can now close socket nnn", but this would keep a number of socket descriptors open in the listening process and add some overhead as well.
I know I can force the socket to start the shutdown process by calling shutdown() directly from either process, but I want to prevent it.
I assume there exists a simple solution, but I cannot find it.
Question
Is there a way to de-register the socket descriptor from the listening process such that it is no longer in the file descriptor table of the process, but without activating the socket shutdown?
Source code
The SCM_RIGHTS implementation used to send the socket is here (send_fds and native_close):
https://github.com/kenkendk/SockRock/blob/master/src/ScmRightsImplementation.cs
The code that sends the socket and then closes it is here:
https://github.com/kenkendk/ceenhttpd/blob/master/Ceen.Httpd.Cli/Runner/SubProcess/SpawnRemoteInstance.cs#L488-L497
If I comment out line 497 everything works, but obviously get a large file descriptors leak.
The receiving end of SCM_RIGHTS is here:
https://github.com/kenkendk/ceenhttpd/blob/master/Ceen.Httpd.Cli/Runner/SubProcess/SpawnedRunner.cs#L313
tl;dr: The socket is closed when the last reference is closed.
The answer to my question is most likely:
No, there is no way to prevent the socket shutdown, but it is not needed as the socket will not close until the last descriptor has closed.
The answer from Andrew was correct, and got me on track: it makes no sense, others do the same all the time.
In the end, the problem was a timeout in the handler process that closed the socket, but that made it look like the close() call from the listener was the problem.
When I stopped the close() call from the listening process, it started working. This happens because then the timeout correctly closes the handle, but there is still a reference (in the listening process) so the socket stays open.
I use RabbitMQ.Client (runtime version v2.0.50727, version 2.8.1.0) with C# .NET application.
I create connection like this:
using (IConnection connection = _factory.CreateConnection())
{
using (IModel channel = connection.CreateModel())
{
// code...
}
}
If I close the application properly, it simply closes the channel and connection. But if application is closed incorrectly (e.g. pressing restart button on PC), it is not. I would like to ensure that all unnecessary connections (from previous sessions or even other applications, if by mistake other instance of the application is running somewhere else) are closed before I start my application.
I know I may use heart beats but it is possible that my application requires really much time to start doing anything (many hours of opened connection and not being used). So I think heartbeat is not the best thing.
How can I close all opened connections for RMQ? (Or, even better, all opened connections, with the exception for one given IP)?
Regards!
I encountered the same problem as you. I tried a lot of methods to close those connections.
Those methods, some are works some are only part works. Maybe you can have a try.
Use rabbitmqctl command to delete the queues then use RMQ's management website close the connections. It means current opened queues will expire after 1 second(1000 miliseconds). This way all queues are deleted. Then you can close connections.
Command:
rabbitmqctl set_policy expiry ".*" '{"expires":1000}' --apply-to queues
Queue Time-To-Live policy--> https://www.rabbitmq.com/ttl.html
This method works partly.
After searching, got the idea that reason might be:
Your producer waiting the return ACK back, it won't be destroyed untill you send ACK to acknowledge the job has finished.
Abrupt way. Works. RMQ save connections information in its DB menisa.
Step1: Stop rabbitmq-server first, and kill rabbitmq thread by 'ps aux | grep rabbitmq' to find its pid then kill all rabbitmq thread.
Find RMQ DB mensia location
(1). $> cd /var/lib/rabbitmq/
Step2: rename mensia file to another name to "delete"
(2). $> mv mensia mensia-bak
Step3: restart rabbitmq-server
The third methods works for me now. It can close all open connections.
Sounds like Heartbeats is your best solution. I added heartbeats to my RabbitMQ apps for the same reason (ungraceful shutdowns). It shouldn't matter that there is a long gap of time between messages, heartbeat will just verify that the connection is still open on both sides.
I had the same problem when I open worker in console and than stop it with ctrl+c. After than process is closed but connection is still there and it's visible in admin panel.
One solution is to close connection in RabbitMQ Admin panel
or you can found the process and kill it manual sudo kill -9 pid
or when you open an connection set HEARTBEAT. Read [Dead TCP Connections]
I've created an asynchronous server in C# to go along with my Android application. The server is similar to this: http://msdn.microsoft.com/en-us/library/fx6588te.aspx
It works well and I can have many clients connect and receive data from the server at the same time. One problem that I've found is that in my Android app if you are already connected over Wifi and press the connect button again, the server spawns a new socket. The server should kill the old connection first and then create a new connection. On the Android side I make sure to call close() and even set it to null afterwards. I also send a disconnect control signal to the server so that it can also call close() on the socket. For example, here's how I do it in the server:
if (state.storage.parseJson(content) == JsonStorage.DISCONNECT)
{
Console.WriteLine("Disconnect2!");
state.workSocket.Shutdown(SocketShutdown.Both);
state.workSocket.Close();
return;
}
When I inspect my server process in a program called "CurrPorts" it shows several connections open to my Android device on different ports. I send data to my clients using a Timer object, and I also check to see if the connection is active otherwise I close it. For example, my TimerCallback method:
public void TimeCallBack(object input)
{
StateObject state = (StateObject)input;
if (state.workSocket.Connected)
{
Send(state.workSocket, state.storage.getJson());
}
else
{
Console.WriteLine("Dispose!");
state.timer.Dispose();
state.workSocket.Close();
}
}
I can't think of why my server isn't closing old connections. There should only be as many connections open as devices connected to the server. If this were a threaded blocking server then it would be easy to just close the thread down, but I'm not sure what to do in this case.
edit: so I just refreshed the CurrPorts program after letting it sit for a while and it dropped down to one established connection. Is my solution right and it just takes a while for Windows to actually clear the old socket connections that were created?
Yes, Windows will keep around the information about the socket for a while. You can see this with netstat, closed sockets will show a state of TIME_WAIT after they are closed and even after the application that hosted the socket has terminated.
If a detach a serial device which is still being used by windows, SerialPort.GetPortNames() will return that same detached device as actually still being attached. I also can't close the serial port without an unhandeled exception error stating that the port does not exist (which is true).
I can confirm that the device map for SERIALCOMM in the registry is not being updated either, which is where SerialPort.GetPortNames() gets the port names I presume. The hardware manager detects the right COMM ports.
Is there a way around this? Can I simply delete the SERIALCOMM registry entry?
I looked at this potential workaround, but I think that will just let me catch the exception.
I'm not an expert but my experience is that as long as you have any (SW-)object connected to the com-port it will be visible.
When I tested this some years ago I got the same result and not until I did lose my SerialPort object the port disappeared from the GetPortNames list (and presumable also the registry).
I think this is the way Windows handles this driver. If a serial port gets unplugged while in use in SW the system continues to have a place-holder for the serial port until it is released by SW.
In my SW I solved this by having a timeout for the function I needed (the other end could stop working as well) and before every new start of program-loop (normally once every 5min-1h) I just released the COM-port and reconnected to it, if reconnect failed the port was detected as lost...
Hope this helps you.
I want to close a socket so I can reopen one on the same port but I do not have a handle on that socket.
How can I get the socket that is listening on localhost:873 to close it?
Without a kernel driver this is not possible. It is not legal in Windows to grab a socket handle in another process and close it proactively.
Only that process that owns the socket can close it, so all you could try is ending the process that owns the socket.
From the command line you can find the Process ID of the process using a particular socket using the -o option to netstat. For example:
netstat -noa | findstr LISTENING
I don't know how you do this programmatically in .NET though.
You could investigate SO_REUSEADDR.