8
0
mirror of https://github.com/FirebirdSQL/firebird.git synced 2025-01-23 02:03:04 +01:00

Postfix for #7296: During shutdown op_disconnect may be sent to invalid handle; fixed segfault caused by too early destroyed port_context

This commit is contained in:
AlexPeshkoff 2023-03-17 20:09:25 +03:00
parent 6324d9cece
commit 017f313073

View File

@ -1147,6 +1147,9 @@ inline static void reset(IStatus* status) throw()
inline static void defer_packet(rem_port* port, PACKET* packet, bool sent = false)
{
fb_assert(port->port_flags & PORT_lazy);
fb_assert(port->port_deferred_packets);
// hvlad: passed packet often is rdb->rdb_packet and therefore can be
// changed inside clear_queue. To not confuse caller we must preserve
// packet content
@ -7620,7 +7623,7 @@ static void finalize(rem_port* port)
{
/**************************************
*
* d i s c o n n e c t
* f i n a l i z e
*
**************************************
*
@ -7636,6 +7639,10 @@ static void finalize(rem_port* port)
// Avoid async send during finalize
RefMutexGuard guard(*port->port_write_sync, FB_FUNCTION);
// recheck with mutex taken
if (port->port_flags & PORT_detached)
return;
// Send a disconnect to the server so that it
// gracefully terminates.
@ -7671,14 +7678,13 @@ static void finalize(rem_port* port)
port->send(packet);
}
REMOTE_free_packet(port, packet);
delete rdb;
port->port_context = nullptr;
}
// Cleanup the queue
delete port->port_deferred_packets;
port->port_deferred_packets = nullptr;
port->port_flags &= ~PORT_lazy;
port->port_flags |= PORT_detached;
}
@ -7698,6 +7704,9 @@ static void disconnect(rem_port* port, bool rmRef)
finalize(port);
Rdb* rdb = port->port_context;
port->port_context = nullptr;
// Clear context reference for the associated event handler
// to avoid SEGV during shutdown
@ -7712,6 +7721,7 @@ static void disconnect(rem_port* port, bool rmRef)
port->port_flags |= PORT_disconnect;
port->disconnect();
delete rdb;
// Remove from active ports
@ -9022,17 +9032,20 @@ static void send_partial_packet(rem_port* port, PACKET* packet)
// Send packets that were deferred
for (rem_que_packet* p = port->port_deferred_packets->begin();
p < port->port_deferred_packets->end(); p++)
if (port->port_deferred_packets)
{
if (!p->sent)
for (rem_que_packet* p = port->port_deferred_packets->begin();
p < port->port_deferred_packets->end(); p++)
{
if (!port->send_partial(&p->packet))
if (!p->sent)
{
(Arg::Gds(isc_net_write_err) <<
Arg::Gds(isc_random) << "send_partial_packet/send_partial").raise();
if (!port->send_partial(&p->packet))
{
(Arg::Gds(isc_net_write_err) <<
Arg::Gds(isc_random) << "send_partial_packet/send_partial").raise();
}
p->sent = true;
}
p->sent = true;
}
}