Closed vadi2 closed 5 years ago
@SlySven handing this over to you as you're across this locking code and how it works, could you have a look?
Oh, that problem is because something - in this case the slot cTelnet::handle_socket_signal_disconnected
has been called (asynchronously) from the Qt (network?) library code and has (indirectly) called the slot mudlet::slot_newDataOnHost
which needs to get the calling Host
instance given that it does know the name it is using. This is a problem because it is trying to look it up (by using (Host*) getHost(const QString& hostname)
to read (QMap<QString, QSharedPointer<Host>>) HostManager::mHostPool
{thereby taking a shared read-lock on that) at the same time as another thread (probably our main Mudlet application one) is changing that QMap
and that has a (higher priority, exclusive) write-lock on it.
This is probably the process that is closing the Neon MOO - and I guess the contending thread is probably one associated with the Achaea profile (either our main Mudlet one or one created by another part of the Qt libraries) - that being the case we need to where that is changing HostManager::mHostPool
and try to shorten the time it holds the write lock...
BTW In reviewing the code that might be causing this I see that (void) mudlet::slot_close_profile_requested(int)
is used to close a profile when multi-playing and the close button is used on the tab-bar; however (void) mudlet::slot_close_profile()
is never used - I am guessing that closure of a profile otherwise (when only one user profile is open) is handled by other means - I haven't yet pinned down where that happens but I will - even if it is just to clarify things for myself...
Oh, that is not nice - that mPoolReadWriteLock.lockForRead();
in HostManager::getHost(QString hostname)
is being hit whilst the same profile has already got a write lock in HostManager::deleteHost(const QString& hostname)
- there is around 32 stack-frames in between:
This is going to take a good think...
Okay found a workaround for that point, but then got another one from the Host::raiseEvent()
... call - more thinking in progress...
I think the problem is partly cause by a gratuitous use of mTelnet.disconnect();
in the Host
destructor - it is far too late to be doing that there as it triggers signals and slots - such as cTelnet::handle_socket_signal_disconnected()
and cTelnet::signal_disconnected(Host*)
which is a really bad idea by then... :boom:
I am looking at the profile closing code and I can see some clean up steps (including the elimination of a goto
in TConsole::closeEvent(QCloseEvent*)
) that can be done.
Just be careful and test that sysDisconnectionEvent
is still raised in the same behaviour and Lua code doesn't crash when calling Mudlet API (because some things like Host
are already destroyed) (https://github.com/Mudlet/Mudlet/issues/512)
Just to confirm but it is not surprising. FreeBSD locks up in exactly the same manner in the same place; though. given the code structure, I'd expect this to be on all platforms.
I think I can fix this. I just need to establish a uniform sequence of steps in the closing of one profile/more profiles/the whole application and ensure that the slot cTelnet::handle_socket_signal_disconnected()
or the badly named cTelnet::disconnect()
+ are not called asynchronously by the signal QAbstractSocket::disconnected()
too late in the profile closing process to be handled correctly.
As it happens, putting a mTelnet.disconnect();
in the Host
destructor does not seem like a good idea in this context!
+ - badly named because Ì think it erroneously overloads(?) the non-static QObject::disconnect()
overload with all three default argument which disconnects all slots connected to the object concerned - the cTelnet
instance in this case.
Brief summary of issue / Description of requested feature:
Mudlet freezes when closing secure profile with self-signed certificates on Linux.
Steps to reproduce the issue / Reasons for adding feature:
moo.neon-moo.space:7778
and enableAccept self-signed certificates
in order for the connection to workachaea.com:23
)mPoolReadWriteLock.lockForRead();
inHostManager::getHost(QString hostname)
Error output / Expected result of feature
Mudlet should not freeze.
Extra information, such as Mudlet version, operating system and ideas for how to solve / implement:
Mudlet 3.17.0 on Linux.