Commit
8d939c08 (rx: avoid nat ping during shutdown) added a call
to shutdown_rx() inside the DARWIN shutdown sequence, before the rx
socket was closed. From the commit message, it sounds like this was
done to avoid NAT pings from calling osi_NetSend during the shutdown
sequence after the rx socket was closed; calling shutdown_rx() before
closing the socket would cause any connections we had to be destroyed
first, avoiding that.
The problem with this is that this means shutdown_rx() is called when
osi_StopNetIfPoller is called, which is much earlier than some other
portions of the shutdown sequence; some of which may hold references
to e.g. rx connections. If we try to, for instance, destroy an rx
connection after shutdown_rx() is called, we could panic.
An earlier version of that commit (gerrit PS1) just tried to insert a
check before the relevant osi_NetSend call, making us just skip the
osi_NetSend if the shutdown sequence had been started. So to avoid the
above issue, try to implement that approach instead. And instead of
doing it just for NAT pings, we can do it for almost all osi_NetSend
calls (besides those involved in the shutdown sequence itself), by
checking this in rxi_NetSend. Also return an error (ESHUTDOWN) if we
skip the osi_NetSend call, so we're not completely silent about doing
so.
This means we also remove the call to shutdown_rx() inside DARWIN's
osi_StopNetIfPoller(). This allows us to interact with Rx objects
during more of the shutdown process in cross-platform code.
Change-Id: I4e631b28d090635aeacd59de0fd237d572f97e93
Reviewed-on: https://gerrit.openafs.org/13718
Reviewed-by: Mark Vitale <mvitale@sinenomine.net>
Reviewed-by: Benjamin Kaduk <kaduk@mit.edu>
Tested-by: BuildBot <buildbot@rampaginggeek.com>
void
osi_StopNetIfPoller(void)
{
- shutdown_rx();
soclose(rx_socket);
if (afs_termState == AFSOP_STOP_NETIF) {
afs_termState = AFSOP_STOP_COMPLETE;
rxi_NetSend(osi_socket socket, void *addr, struct iovec *dvec,
int nvecs, int length, int istack)
{
- return osi_NetSend(socket, addr, dvec, nvecs, length, istack);
+ if (rxi_IsRunning()) {
+ return osi_NetSend(socket, addr, dvec, nvecs, length, istack);
+ }
+#ifdef AFS_NT40_ENV
+ return WSAESHUTDOWN;
+#else
+ return ESHUTDOWN;
+#endif
}