Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Acceptor.Stop() then restart doesn't work? #196

Open
gbirchmeier opened this issue May 16, 2013 · 2 comments
Open

Acceptor.Stop() then restart doesn't work? #196

gbirchmeier opened this issue May 16, 2013 · 2 comments

Comments

@gbirchmeier
Copy link
Member

Reported by @TomasVetrovsky in #185. Needs verification.

If a fix is needed, maybe this and #185 can be fixed together.

@huwmjenkins
Copy link
Contributor

This is definitely an issue and I've made some changes that seem to fix it and, as such, I've created a pull request for this issue.

https://github.com/connamara/quickfixn/pull/351/files

At it's basic the issue is that the "Acceptor.Start()" method only calls the "StartAcceptingConnections()" method if the isStarted_ flag is false:

public void Start()
{
lock (sync_)
{
if (!isStarted_)
{
StartAcceptingConnections();
isStarted_ = true;
}
}
}

but when you call "Acceptor.Stop()" it doesn't do anything to this flag so calling Start() after Stop() effectively does nothing:

public void Stop(bool force)
{
lock( sync_ )
{
StopAcceptingConnections();
LogoutAllSessions( force );
}
/// FIXME StopSessionTimer();
/// FIXME Session.UnregisterSessions(GetSessions());
}

Unfortunately, simply setting the isStarted_ flag at this point to false doesn't work as the StartAcceptingConnections method calls the Start method on the SocketReactor which subsequently calls the Run method which only actually runs if the ReactorState is set to State.Running but the start method doesn't do this so it's left in the SHUTDOWN_COMPLETED state:

public void Start()
{
serverThread_ = new Thread( new ThreadStart( Run ) );
serverThread_.Start();
}

public void Run()
{
tcpListener_.Start();
while (State.RUNNING == ReactorState)
{
...
}
ShutdownClientHandlerThreads();
}

Unfortunately, setting the ReactorState in the Start method to State.RUNNING didn't work either as the Session/SocketReader starts complaining "Multiple logons/connections for this session are not allowed" as it looks like the SocketReader and/or the Session has not been closed/logged out correctly during the shutdown.

This was due to the non-implementation of WaitForLogout in the socket acceptor. So I've implemented this method.

However, that didn't finally resolve it as there were some threading issues.
First was the ClientHandlerThread could be disposed but the SocketReactor could still call the log method which would throw a null reference so I just added null check to the Log method in ClientHandlerthread:

public void Log(string s)
{
var log = log_;
if( log != null )
{
log.OnEvent( s );
}
}

The next issue was that the Run method in SocketReactor used the blocking AcceptTcpClient which meant that even if the state was changed the ShutdownClientHandlerthreads would never be called. So I've changed this to a sleep based loop using TcpListener.Pending:

if( !tcpListener_.Pending() )
{
new ManualResetEvent(false).WaitOne(100);
continue;
}

though I think moving to using the BeginAcceptTcpClient/EndAcceptTcpClient asynchronous methods might be a better approach. Unfortunately, I have to work on something else just now but I might look into this next time I have a spare moment.

The other change I made was that the start of the run method would call TcpListener.Start. However, if someone called stop before this method had finished it could leave the class in the SHUTDOWN_REQUESTED state so I moved the call to start to before the Run thread is started.

Anyway, I've added some tests around the ThreadedSocketAccecptor in terms of starting and stopping and logging on to test various scenarios.

Huw

@VAllens
Copy link

VAllens commented Aug 23, 2021

Hi guys. Any progress?
I have restart business scenarios.
When I call the Stop method and then call the Start method, it doesn't works.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants