@ -45,7 +45,7 @@ namespace Avalonia.X11
private readonly CancellationTokenSource _ cancellationTokenSource = new CancellationTokenSource ( ) ;
private readonly CancellationTokenSource _ cancellationTokenSource = new CancellationTokenSource ( ) ;
private readonly IntPtr _ currentIceConn ;
private readonly IntPtr _ currentIceConn ;
private readonly IntPtr _ currentSmcConn ;
private IntPtr _ currentSmcConn ;
private bool _ saveYourselfPhase ;
private bool _ saveYourselfPhase ;
@ -106,11 +106,17 @@ namespace Avalonia.X11
public void Dispose ( )
public void Dispose ( )
{
{
if ( _ currentSmcConn = = IntPtr . Zero ) return ;
// Reachable from the Die callback, from HandleRequests() and from platform teardown,
// but SmcCloseConnection frees both the SmcConn and its IceConn.
var smcConn = Interlocked . Exchange ( ref _ currentSmcConn , IntPtr . Zero ) ;
if ( smcConn = = IntPtr . Zero ) return ;
s_nativeToManagedMapper . TryRemove ( _ currentSmcConn , out _ ) ;
// The pump would otherwise keep using the IceConn we are about to free.
_ cancellationTokenSource . Cancel ( ) ;
_ = SMLib . SmcCloseConnection ( _ currentSmcConn , 1 ,
s_nativeToManagedMapper . TryRemove ( smcConn , out _ ) ;
_ = SMLib . SmcCloseConnection ( smcConn , 1 ,
new [ ] { $"{nameof(X11PlatformLifetimeEvents)} was disposed in managed code." } ) ;
new [ ] { $"{nameof(X11PlatformLifetimeEvents)} was disposed in managed code." } ) ;
}
}
@ -172,6 +178,8 @@ namespace Avalonia.X11
private void HandleRequests ( )
private void HandleRequests ( )
{
{
if ( _ cancellationTokenSource . IsCancellationRequested ) return ;
if ( ICELib . IceProcessMessages ( _ currentIceConn , out _ , out _ ) = =
if ( ICELib . IceProcessMessages ( _ currentIceConn , out _ , out _ ) = =
ICELib . IceProcessMessagesStatus . IceProcessMessagesIoError )
ICELib . IceProcessMessagesStatus . IceProcessMessagesIoError )
{
{
@ -188,8 +196,9 @@ namespace Avalonia.X11
private void ShutdownCancelledHandler ( )
private void ShutdownCancelledHandler ( )
{
{
if ( _ saveYourselfPhase )
var smcConn = _ currentSmcConn ;
SMLib . SmcSaveYourselfDone ( _ currentSmcConn , true ) ;
if ( _ saveYourselfPhase & & smcConn ! = IntPtr . Zero )
SMLib . SmcSaveYourselfDone ( smcConn , true ) ;
_ saveYourselfPhase = false ;
_ saveYourselfPhase = false ;
}
}