Refering here:
Generally, an application should call CloseHandle once for each handle it opens. It is usually not necessary to call CloseHandle if a function that uses a handle fails with ERROR_INVALID_HANDLE, because this error usually indicates that the handle is already invalidated. However, some functions use ERROR_INVALID_HANDLE to indicate that the object itself is no longer valid. For example, a function that attempts to use a handle to a file on a network might fail with ERROR_INVALID_HANDLE if the network connection is severed, because the file object is no longer available. In this case, the application should close the handle. https://learn.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-closehandle
I just don't understand. So if connection is severed and I try to close a handle will it fail because handle is invalid? But what will happen if connection is restored? Main application process will restore it's ownership over a file? If I am right, it's a big leak. And how to handle this scenario? Is there any standart way?
The following explanation may answer your questions.
From Raymond Chen's blog,
Forcing a network file handle closed does not actually close the
handle. This makes it very different from the various “force handle
closed” utilities out there. Rather, forcing a network file handle
closed is accomplished by simulating a network failure, so that when
the remote machine tries to use the handle again, it’s told, “Wha? I’m
sorry, we must have a bad connection, because I’m not sure what you’re
talking about.” Since programs which access network resources must
deal with the possibility of network connectivity loss, this deception
does not violate the interface contract.
(Doing this to handles to local resources is a much riskier
undertaking, because applications expect access to local files to
remain valid for the lifetime of the handle. There is no equivalent of
transient network connectivity failure for local files on
non-removable drives. There is also no API for simulating it.)
Hope to help you.
Related
I am writing a socket program in c++. The program runs on a set of cluster machines.
I just entered into the socket programming and just learned how to send and receive. I think that, during the long running of the program, some TCP connections can get lost. In that case, re-connecting the server and client smoothly is necessary.
I wonder if there is a well-known basic mechanism (or algorithm? protocol?) to achieve it. I found that there are many many socket error codes with different semantics, which makes me hard to start.
Can any one suggest any reference code that I can learn from?
Thanks,
It's not complicated. The only two error codes that aren't fatal to the connection are:
EAGAIN/EWOULDBLOCK, which are in fact two names for the same number, and mean that it is OK to re-attempt the operation after a period, or after select()/poll()/epoll() has so indicated;
EINTR, which just means 'interrupted system call' - try again.
All others are fatal to the connection and should cause to you close it.
The actual, specific error code, is irrelevant. If you have an active socket connection, a failed read or a write indicates that the connection is gone. The error code perhaps gives you some explanation, but it's a bit too late now. The socket is gone. It is no more. It ceased to exist. It's an ex-socket. You can use the error code to come up with a colorful explanation, but it would be little more than some minor consolation. No matter what was the specific reason, but your socket is gone and you have to deal with it.
When using non-blocking sockets there are certain specific return codes and errno values that indicate that the socket is still fine, but just is not ready to read or write anything, that you'll have to specifically check for, and handle. This would be the only exception to this.
Also, EINTR usually does not necessarily mean that the socket is really broken; so that might be another exception to check for.
Once you have a broken socket, the only general design principle, if there is one, is that you have to close() it as the first order of business. The file descriptor is completely useless. After that point, it's entirely up to you what to do next. There are no rules, etched in stone, for this situation. Typically, applications would log an error, in some form or fashion, or attempt to make another connection. It's generally up to you to figure out what to do.
About the only "well-known basic mechanism" in socket programming is explicit timeouts. Network errors, and failures, don't always get immediately detected by the underlying operating system. When a networking problem occurs, it is not always immediately detectable. It can take many minutes before the protocol stack declares a broken socket, and gives you an error indication.
So, if you're coding a particular application, and you know that you should expect to read or write something within some prescribed time frame, a common design pattern is to code an explicit timeout, and if nothing happens when the timeout expires, assume that the socket is broken -- even if you have no explicit error indication otherwise -- close() it, then proceed to the next step.
I have a program that uses services from others. If the program crashes, what is the best way to close those services? At server side, I would define some checkers that monitor if a client is invalid periodically. But can we do any thing at client? I am not the sure if the normal RAII still works at this case. My code is written in C and C++.
If your application experiences a hard crash, then no, your carefully crafted cleanup code will not run, whether it is part of an RAII paradigm or a method you call at the end of main. None of an application's cleanup code runs after a crash that causes the application to be terminated.
Of course, this is not true for exceptions. Although those might eventually cause the application to be terminated, they still trigger this termination in a controlled way. Generally, the runtime library will catch an unhandled exception and trigger termination. Along the way, your RAII-based cleanup code will be executed, unless it also throws an exception. Then you're back to being unceremoniously ripped out of memory.
But even if your application's cleanup code can't run, the operating system will still attempt to clean up after you. This solves the problem of unreleased memory, handles, and other system objects. In general, if you crash, you need not worry about releasing these things. Your application's state is inconsistent, so trying to execute a bunch of cleanup code will just lead to unpredictable and potentially erroneous behavior, not to mention wasting a bunch of time. Just crash and let the system deal with your mess. As Raymond Chen puts it:
The building is being demolished. Don't bother sweeping the floor and emptying the trash cans and erasing the whiteboards. And don't line up at the exit to the building so everybody can move their in/out magnet to out. All you're doing is making the demolition team wait for you to finish these pointless housecleaning tasks.
Do what you must; skip everything else.
The only problem with this approach is, as you suggest in this question, when you're managing resources that are not controlled by the operating system, such as a remote resource on another system. In that case, there is very little you can do. The best scenario is to make your application as robust as possible so that it doesn't crash, but even that is not a perfect solution. Consider what happens when the power is lost, e.g. because a user's cat pulled the cord from the wall. No cleanup code could possibly run then, so even if your application never crashes, there may be termination events that are outside of your control. Therefore, your external resources must be robust in the event of failure. Time-outs are a standard method, and a much better solution than polling.
Another possible solution, depending on the particular use case, is to run consistency-checking and cleanup code at application initialization. This might be something that you would do for a service that is intended to run continuously and will be restarted promptly after termination. The next time it restarts, it checks its data and/or external resources for consistency, releases and/or re-initializes them as necessary, and then continues on as normal. Obviously this is a bad solution for a typical application, because there is no guarantee that the user will relaunch it in a timely manner.
As the other answers make clear, hoping to clean up after an uncontrolled crash (i.e., a failure which doesn't trigger the C++ exception unwind mechanism) is probably a path to nowhere. Even if you cover some cases, there will be other cases that fail and you are building in a serious vulnerability to those cases.
You mention that the source of the crashes is that you are "us[ing] services from others". I take this to mean that you are running untrusted code in-process, which is the potential source of crashes. In this case, you might consider running the untrusted code "out of process" and communicating back to your main process through a pipe or shared memory or whatever. Then you isolate the crashes this child process, and can do controlled cleanup in your main process. A separate process is really the lightest weight thing you can do that gives you the strong isolation you need to avoid corruption in the calling code.
If forking a process per-call is performance-prohibitive, you can try to keep the child process alive for multiple calls.
One approach would be for your program to have two modes: normal operation and monitoring.
When started in a usual way, it would :
Act as a background monitor.
Launch a subprocess of itself, passing it an internal argument (something that wouldn't clash with normal arguments passed to it, if any).
When the subprocess exists, it would release any resources held at the server.
When started with the internal argument, it would:
Expose the user interface and "act normally", using the resources of the server.
You might look into atexit, which may give you the functionality you need to release resources upon program termination. I don't believe it is infallible, though.
Having said that, however, you should really be focusing on making sure your program doesn't crash; if you're hitting an error that is "unrecoverable", you should still invest in some error-handling code. If the error is caused by a Seg-Fault or some other similar OS-related error, you can either enable SEH exceptions (not sure if this is Windows-specific or not) to enable you to catch them with a normal try-catch block, or write some Signal Handlers to intercept those errors and deal with them.
I have an out of process com server, specifying CLSCTX_LOCAL_SERVER as the context, and REGCLS_MULTIPLEUSE for the connection type. This results in a single server process being reused by multiple calls from multiple clients.
I’m now wanting to make some changes to the server, which unfortunately can not work with a single process shared amongst clients (there are reasons for this, but they're long winded). I know you can set the server to use REGCLS_SINGLEUSE as the connection type, and this will create a new process for the OOP server each call. This solves my issue, but is a non-starter in terms of process usage; multiple calls over short periods result in many processes and this particular server might be hit incredibly often.
Does anyone happen to know of a mechanism to mix those two connection types? Essentially what I want is a single server process per calling process. (ie, client one creates a process, and that process is reused for subsequent calls from that client. Client two tries to call the server, and a new process is created). I suspect I could achieve it by forcing a REGCLS_SINGLEUSE server to stay open permanently in the client, but this is neither elegant nor possible (since I can’t change one of the clients).
Thoughts?
UPDATE
As expected, it seems there is no way to do this. If time and resource permitted I would most likely convert this to an In-Proc solution. For now though, I'm having to go with the new behaviour being used for any calling client. Fortunately, the impact of this change is incredibly small, and acceptable by the clients. I'll look into more drastic and appropriate changes later.
NOTE
I've marked Hans' reply as the answer, as it does in fact give a solution to the problem which maintains the OOP solution. I merely don't have capacity to implement it.
cal
COM does not support this activation scenario. It is supposed to be covered by an in-process server, do make sure that isn't the way you want to do it given its rather major advantages.
Using REGCLS_SINGLEUSE is the alternative, but this requires you extending your object model to avoid the storm of server instances you now create. The Application coclass is the boilerplate approach. Provide it with factory methods that gives you instances to your existing interfaces.
I'll mention a drastically different approach, one I used when I wanted to solve the same problem as well but required an out-of-process server to take advantage of bridging a bitness gap. You are not stuck with COM launching the server process for you, a client can start it as well. Provided of course that it knows enough about the server's installation location. Now a client of course has complete control over the server instance. The server called CoRegisterClassObject() with an altered CLSID, I xored part of the guid with the process ID. The client did the same so it always connected with the correct server. Extra code was required in the client to ensure it waits long enough to give the server a chance to register its object factories. Worked well.
So I have a service method that uses io_service::poll() to process any currently-ready read/write events:
void Foo::service()
{
io.poll(); // boost::asio::io_service
if (socket.is_open())
if (socket.available())
notifyReadyToRead();
else
notifyReadyToWrite();
}
However, I'd also like to trigger behavior if the remote socket closes (gracefully or otherwise). I know that Winsock can handle this, as it raises a network event in this circumstance. Boost Asio sockets, however, have no built-in support for this as far as I can see.
I've tried reading and writing a zero-byte packet to the socket to test it for errors, but it appears that the implementation simply bails successfully if you pass it boost::asio::buffer(socket, 0) without actually checking the socket.
I've also heard that leaving a hanging read operation could work, but I'm not sure how to manage this while still allowing regular boost::asio::read and 'boost::asio::write` operations to work correctly.
Finally, adding a ping operation to the app-level protocol is a no-go; this class is intended to be used generically, and even if it wasn't I cannot change the remote side's protocol.
While I'd prefer a portable solution, a Windows-specific solution would be sufficient, even if it means grabbing the native handle and enumerating events that way. (This occurred to me, but WSAEnumNetworkEvents clears the internal record of events, so I suspect it would cause problems if the boost::asio implementation depended on reading it.)
In general case, you have to implement some application-level mechanism to detect all kinds of disconnection.
There were numerous discussions on boost/asio ML on this topic, here is on of them.
You can enable the socket option TCP_KEEPALIVE, but still need a pending read operation in order to receive a notification of the failed read.
I am making a server and I use fork() for creating child processes but I have doubts about that. Here are some:
Why do you need to close main socket in a child process and new connection accepted socket in the parent process? (after accepting a new connection) I thought that sockets are only integers with some id which are used to access opened sockets in some system-wide object which is only acceptable through system functions calls. In that case fork would only copy the integer but would have no affect on socket opened.
I have checked and found out that if I fork a process inside a class method, all members are copied. Well, I have found out it is copy-on-edit so does it mean that my server class will be copied in each child that uses a non-constant function? How do I make some memory shared between all such processes (like a list of tasks and each child puts something into it while the parent is reading stuff from it)? I guess fork is not the right function for that. What is the best way?
P.S. I am pretty sure I know the answer to the second question, which is clone(), but just wanted to make sure that's the right function.
Sockets in Unix are File descriptors and they are indeed integers, as seen by the user, but they really are indexes into a table that the kernel maintains per process. In this table each file descriptor (FD) refers to an open file description (OFD) that are system-wide objects maintained in kernel. When you do fork() the opened file descriptors are duplicated and both child's and parent's point to the same OFD. Having two FDs that refer to the same OFD is not usually a problem, but particularly with sockets they can have subtle problems, as the connection is closed only when you close all the FDs that refer to it.
You should really consider using threads (do not close the sockets if you use threads!). clone is a linux system call and is not intended to be used directly. Your alternative is to use shared memory but it is kind of more complex.
The int is a handle, but the socket itself is still associated with the process. The child closes the listening socket mainly for safety reasons (it doesn't need it, and if the child ever spawns another process, that process would inherit the socket as well); the server process closes the new connection's socket because otherwise the connection would remain open until the server process exits (the socket exists as long as at least one process still has a handle to it).
You either want multithreading or a proper shared memory approach. This is where the fun begins.
Shared memory between independent processes comes with interesting problems, but also provides otherwise impossible capabilities (for example, you can restart the master server process and leave the processes serving open connections running, which is difficult to get right as two different versions of the service then have to talk to each other, but allows seamless upgrades without disconnecting clients or interrupting service).
Sharing memory between threads is relatively easy, but threads share the same set of file descriptors, so you do not win much here.
Last, there is a third alternative: an event loop watching multiple sockets, giving attention to each only if something is actually happening. Look at the documentation for the select and poll functions.
Forking duplicates file descriptors, so you have to close the duplicate.
Forking also effectively copies all memory (though in practice it's copy-on-write, so it's not very expensive). You make a new process which is entirely separate from the parent process, unless you explicitly set up some shared memory.
Maybe you intended to spawn a new thread rather than forking a new process?
I think you might want to look through this book as a reference on fork().
Yes you do need to close the socket bound to listen in the child and accepted socket in the parent. The integers aka file handles point to real structures see this so unless you want the kernel to dump a new connection on a child or parent being able to send the data to the connected client you might want to prevent this outright.
To share data for between the processes the best way is shared memory. The book I referred you to will have quite a bit of information regarding that too. In general if you need to share memory without shared memory then you might want to look at threads.
P.S. I'm not sure which clone() method you are referring to. Object copying is done via copy constructors.