Why would the implementation differ from the NFS V3 standard, which is an RPC 
over either TCP or UDP?  UDP is completely stateless. Using TCP, clients 
connect to the port and then start sending messages. The connection can be torn 
away at any time by either end.  There is no guaranteed delivery or guaranteed 
response. If the client doesn't receive a response, the server may, or may not, 
have received and processed it.  Naturally this is a problem for non-idempotent 
messages but there are client-side ways to deal with that, like server-side 
request cache, transactions or metadata exclusivity (e.g. the EXCLUSIVE mode on 
a CREATE: https://tools.ietf.org/html/rfc1813#page-54)

I would argue a server can stop at any time for any reason. One can even add to 
the RCP session creation/tear down which could be used for graceful shutdown. 
But that happens at the RPC implementation layer, not the protocol layer.


From: Mario Emmenlauer [mailto:[email protected]]
Sent: Wednesday, February 28, 2018 9:19 AM
To: [email protected]
Subject: Re: Unable to stop socket server while there are connected clients


Dear Robin,

On 28.02.2018 14:19, Robin Coe wrote:
> Not having looked at the bug report, so take this advice as appropriate,
> but I would rethink the implementation. The underlying network protocol
> has no expectation that a server closes a socket, it is always the client's
> responsibility. Data integrity is in question when the server just
> forcibly closed the connection, and why java responds with a socket
> exception in the client.
>
> A safer approach is to implement a callback mechanism that allows the
> server to broadcast that it is being shutdown and allow the clients to
> respond. Once clients have closed the connection, then the server daemon
> can terminate.

I fully agree to your argument as long as we are considering well-
behaving clients. However a problem can arise if the client is not so
well-behaving. Basically, if the client fails to disconnect for whatever
reasons, the server can not cleanly shut down and must be killed. In
many applications (or at least in mine) the server side stores central,
valuable information that under no circumstances should be harmed. A
forced server shut down is the last thing I'd like to happen!

I think your proposed protocol is very good! But on top of that, if
clients fail to obey the disconnect-request, the server must have a fall
back to ensure a clean exit. Currently this is not implemented in
some of the thrift servers :-(

PS: I'm not necessarily saying that it must be malicious intentions of
the client to fail to disconnect. If a significant number of clients
are involved, there is a certain chance that some of them may suffer
from unreliable internet connection, may be busy, may be stale, etc...

All the best,

Mario



> On Feb 27, 2018 11:06, "Gianni Ambrosio" 
> <[email protected]><mailto:[email protected]%3e>
> wrote:
>
>> Hi All,
>> I realized the previous link (THRIFT-2696) was related to Delphi (gosh!).
>> C++ implementation had the same problem but seems to be already fixed:
>>
>> https://github.com/apache/thrift/commit/1684c429501e9df9387c
>> b518e660691f032d7926#diff-73a64b6e865fd1b207b30764b9e06033
>>
>> Is it possible to open a ticket for C# too?
>>
>> Regards,
>> Gianni
>>
>> On 27/02/2018 14:09, Gianni Ambrosio wrote:
>>
>>> Hi All,
>>> I was experiencing exacly the same problem reported here with Thrift
>>> 0.9.1:
>>> https://issues.apache.org/jira/browse/THRIFT-2696
>>>
>>> So I moved to the latest thrift version (i.e. 0.11.0) but the problem is
>>> still there!
>>>
>>> I implemented a thrift server with TSimpleServer in C#:
>>>
>>> public class ThriftServer
>>> {
>>> public void start(){
>>> Service.Processor processor = new Service.Processor(serviceHandl
>>> er);
>>> TServerSocket serverTransport = new TServerSocket(ServiceConstants
>>> .ServicePort);
>>> server = new TSimpleServer(processor, serverTransport);
>>> workerThread = new Thread(new ThreadStart(run));
>>> workerThread.Start();
>>> }
>>> private void run(){
>>> server.Serve();
>>> }
>>> public void stop(){
>>> server.Stop();
>>> }
>>> }
>>>
>>> And here is the C++ client implementation:
>>>
>>> void ThriftClient::connect(const std::string& serverIp) {
>>> boost::shared_ptr<apache::thrift::transport::TTransport> socket(new
>>> apache::thrift::transport::TSocket(serverIp.c_str(),
>>> g_Service_constants.ServicePort));
>>> transport = boost::make_shared<apache::thr
>>> ift::transport::TBufferedTransport>(socket);
>>> transport->open();
>>> client = boost::make_shared<ServiceClient>(boost::make_shared<apache:
>>> :thrift::protocol::TBinaryProtocol>(transport));
>>> }
>>>
>>> The problem is that when I close the C# application the application does
>>> not close. But in that state it closes as soon as I close the C++ client
>>> application.
>>> Debugging the C# application, server.Stop() is called but server.Serve()
>>> call does not exit unless the client has been disconnected.
>>> Since the above thrift ticket seems reporting exactly the same issue and
>>> it should be fixed in thrift 0.9.2, what's wrong in my code?
>>>
>>> Best regards,
>>> Gianni
>>>
>>>
>>
>



Viele Gruesse,

Mario Emmenlauer


--
BioDataAnalysis GmbH, Mario Emmenlauer Tel. Buero: +49-89-74677203
Balanstr. 43 mailto: memmenlauer * biodataanalysis.de
D-81669 München http://www.biodataanalysis.de/

________________________________

Reply via email to