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

[PowerLauncher] don't use Environment.Exit(0) and gracefully shutdown… #20450

Merged
merged 1 commit into from
Sep 12, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 15 additions & 18 deletions src/modules/launcher/PowerLauncher/App.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,10 @@ public partial class App : IDisposable, ISingleInstanceApp
{
public static PublicAPIInstance API { get; private set; }

public static CancellationTokenSource NativeThreadCTS { get; private set; }

private static bool _disposed;

private PowerToysRunSettings _settings;
private MainViewModel _mainVM;
private MainWindow _mainWindow;
Expand All @@ -46,6 +49,8 @@ public partial class App : IDisposable, ISingleInstanceApp
[STAThread]
public static void Main()
{
NativeThreadCTS = new CancellationTokenSource();

Log.Info($"Starting PowerToys Run with PID={Environment.ProcessId}", typeof(App));
int powerToysPid = GetPowerToysPId();
if (powerToysPid != 0)
Expand All @@ -67,15 +72,13 @@ public static void Main()
using (var application = new App())
{
application.InitializeComponent();
new Thread(() =>
NativeEventWaiter.WaitForEventLoop(
Constants.RunExitEvent(),
() =>
{
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, Constants.RunExitEvent());
if (eventHandle.WaitOne())
{
Log.Warn("RunExitEvent was signaled. Exiting PowerToys", typeof(App));
ExitPowerToys(application);
}
}).Start();
Log.Warn("RunExitEvent was signaled. Exiting PowerToys", typeof(App));
ExitPowerToys(application);
}, NativeThreadCTS.Token);

if (powerToysPid != 0)
{
Expand Down Expand Up @@ -118,8 +121,8 @@ private void OnStartup(object sender, StartupEventArgs e)
StringMatcher.Instance = _stringMatcher;
_stringMatcher.UserSettingSearchPrecision = _settings.QuerySearchPrecision;

_mainVM = new MainViewModel(_settings);
_mainWindow = new MainWindow(_settings, _mainVM);
_mainVM = new MainViewModel(_settings, NativeThreadCTS.Token);
_mainWindow = new MainWindow(_settings, _mainVM, NativeThreadCTS.Token);
API = new PublicAPIInstance(_settingsVM, _mainVM, _themeManager);
_settingsReader = new SettingsReader(_settings, _themeManager);
_settingsReader.ReadSettings();
Expand Down Expand Up @@ -154,14 +157,7 @@ private static void ExitPowerToys(App app)
{
SingleInstance<App>.SingleInstanceMutex.Close();

try
{
app.Dispose();
}
finally
{
Environment.Exit(0);
}
app.Dispatcher.Invoke(() => app.Shutdown());
}

private static int GetPowerToysPId()
Expand Down Expand Up @@ -194,6 +190,7 @@ private void RegisterExitEvents()

Current.Exit += (s, e) =>
{
NativeThreadCTS.Cancel();
Log.Info("Application.Current.Exit", GetType());
Dispose();
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,18 +12,22 @@ namespace PowerLauncher.Helper
{
public static class NativeEventWaiter
{
public static void WaitForEventLoop(string eventName, Action callback)
public static void WaitForEventLoop(string eventName, Action callback, CancellationToken cancel)
{
new Thread(() =>
{
var eventHandle = new EventWaitHandle(false, EventResetMode.AutoReset, eventName);
while (true)
{
if (eventHandle.WaitOne())
if (WaitHandle.WaitAny(new WaitHandle[] { cancel.WaitHandle, eventHandle }) == 1)
{
Log.Info($"Successfully waited for {eventName}", MethodBase.GetCurrentMethod().DeclaringType);
Application.Current.Dispatcher.Invoke(callback);
}
else
{
return;
}
}
}).Start();
}
Expand Down
7 changes: 5 additions & 2 deletions src/modules/launcher/PowerLauncher/MainWindow.xaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
using PowerLauncher.Telemetry.Events;
using PowerLauncher.ViewModel;
using Wox.Infrastructure.UserSettings;
using CancellationToken = System.Threading.CancellationToken;
using KeyEventArgs = System.Windows.Input.KeyEventArgs;
using Log = Wox.Plugin.Logger.Log;
using Screen = System.Windows.Forms.Screen;
Expand All @@ -30,6 +31,7 @@ public partial class MainWindow : IDisposable
{
private readonly PowerToysRunSettings _settings;
private readonly MainViewModel _viewModel;
private readonly CancellationToken _nativeWaiterCancelToken;
private bool _isTextSetProgrammatically;
private bool _deletePressed;
private HwndSource _hwndSource;
Expand All @@ -38,18 +40,19 @@ public partial class MainWindow : IDisposable
private bool _disposedValue;
private IDisposable _reactiveSubscription;

public MainWindow(PowerToysRunSettings settings, MainViewModel mainVM)
public MainWindow(PowerToysRunSettings settings, MainViewModel mainVM, CancellationToken nativeWaiterCancelToken)
: this()
{
DataContext = mainVM;
_viewModel = mainVM;
_nativeWaiterCancelToken = nativeWaiterCancelToken;
_settings = settings;

InitializeComponent();

_firstDeleteTimer.Elapsed += CheckForFirstDelete;
_firstDeleteTimer.Interval = 1000;
NativeEventWaiter.WaitForEventLoop(Constants.RunSendSettingsTelemetryEvent(), SendSettingsTelemetry);
NativeEventWaiter.WaitForEventLoop(Constants.RunSendSettingsTelemetryEvent(), SendSettingsTelemetry, _nativeWaiterCancelToken);
}

private void SendSettingsTelemetry()
Expand Down
9 changes: 5 additions & 4 deletions src/modules/launcher/PowerLauncher/ViewModel/MainViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ public class MainViewModel : BaseModel, ISavable, IDisposable
private CancellationTokenSource _updateSource;

private CancellationToken _updateToken;
private CancellationToken _nativeWaiterCancelToken;
private bool _saved;
private ushort _hotkeyHandle;

Expand All @@ -59,15 +60,15 @@ public class MainViewModel : BaseModel, ISavable, IDisposable

internal HotkeyManager HotkeyManager { get; private set; }

public MainViewModel(PowerToysRunSettings settings)
public MainViewModel(PowerToysRunSettings settings, CancellationToken nativeThreadCancelToken)
{
_saved = false;
_queryTextBeforeLeaveResults = string.Empty;
_currentQuery = _emptyQuery;
_disposed = false;

_settings = settings ?? throw new ArgumentNullException(nameof(settings));

_nativeWaiterCancelToken = nativeThreadCancelToken;
_historyItemsStorage = new WoxJsonStorage<QueryHistory>();
_userSelectedRecordStorage = new WoxJsonStorage<UserSelectedRecord>();
_history = _historyItemsStorage.Load();
Expand All @@ -92,12 +93,12 @@ public void RegisterHotkey(IntPtr hwnd)
Log.Info("RegisterHotkey()", GetType());

// Allow OOBE to call PowerToys Run.
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherSharedEvent(), OnHotkey);
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherSharedEvent(), OnHotkey, _nativeWaiterCancelToken);

if (_settings.StartedFromPowerToysRunner)
{
// Allow runner to call PowerToys Run from the centralized keyboard hook.
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherCentralizedHookSharedEvent(), OnCentralizedKeyboardHookHotKey);
NativeEventWaiter.WaitForEventLoop(Constants.PowerLauncherCentralizedHookSharedEvent(), OnCentralizedKeyboardHookHotKey, _nativeWaiterCancelToken);
}

_settings.PropertyChanged += (s, e) =>
Expand Down