private void Unload() { if (Disposed || Threads.Count > 0) { return; } Disposed = true; foreach (object Obj in HandleTable.Clear()) { if (Obj is KSession Session) { Session.Dispose(); } } INvDrvServices.UnloadProcess(this); if (NeedsHbAbi && Executables.Count > 0 && Executables[0].FilePath.EndsWith(Homebrew.TemporaryNroSuffix)) { File.Delete(Executables[0].FilePath); } Device.Log.PrintInfo(LogClass.Loader, $"Process {ProcessId} exiting..."); }
protected virtual void Dispose(bool disposing) { if (!_isDisposed && disposing) { _isDisposed = true; KProcess terminationProcess = new KProcess(KernelContext); KThread terminationThread = new KThread(KernelContext); terminationThread.Initialize(0, 0, 0, 3, 0, terminationProcess, ThreadType.Kernel, () => { // Force all threads to exit. lock (KernelContext.Processes) { // Terminate application. foreach (KProcess process in KernelContext.Processes.Values.Where(x => x.Flags.HasFlag(ProcessCreationFlags.IsApplication))) { process.Terminate(); } // The application existed, now surface flinger can exit too. SurfaceFlinger.Dispose(); // Terminate HLE services (must be done after the application is already terminated, // otherwise the application will receive errors due to service termination. foreach (KProcess process in KernelContext.Processes.Values.Where(x => !x.Flags.HasFlag(ProcessCreationFlags.IsApplication))) { process.Terminate(); } } // Exit ourself now! KernelStatic.GetCurrentThread().Exit(); }); terminationThread.Start(); // Wait until the thread is actually started. while (terminationThread.HostThread.ThreadState == ThreadState.Unstarted) { Thread.Sleep(10); } // Wait until the termination thread is done terminating all the other threads. terminationThread.HostThread.Join(); // Destroy nvservices channels as KThread could be waiting on some user events. // This is safe as KThread that are likely to call ioctls are going to be terminated by the post handler hook on the SVC facade. INvDrvServices.Destroy(); AudioManager.Dispose(); AudioOutputManager.Dispose(); AudioInputManager.Dispose(); AudioRendererManager.Dispose(); KernelContext.Dispose(); } }
protected virtual void Dispose(bool disposing) { if (!_isDisposed && disposing) { ConfigurationState.Instance.System.EnableDockedMode.Event -= OnDockedModeChange; _isDisposed = true; SurfaceFlinger.Dispose(); KProcess terminationProcess = new KProcess(KernelContext); KThread terminationThread = new KThread(KernelContext); terminationThread.Initialize(0, 0, 0, 3, 0, terminationProcess, ThreadType.Kernel, () => { // Force all threads to exit. lock (KernelContext.Processes) { foreach (KProcess process in KernelContext.Processes.Values) { process.Terminate(); } } // Exit ourself now! KernelContext.Scheduler.ExitThread(terminationThread); KernelContext.Scheduler.GetCurrentThread().Exit(); KernelContext.Scheduler.RemoveThread(terminationThread); }); terminationThread.Start(); // Wait until the thread is actually started. while (terminationThread.HostThread.ThreadState == ThreadState.Unstarted) { Thread.Sleep(10); } // Wait until the termination thread is done terminating all the other threads. terminationThread.HostThread.Join(); // Destroy nvservices channels as KThread could be waiting on some user events. // This is safe as KThread that are likely to call ioctls are going to be terminated by the post handler hook on the SVC facade. INvDrvServices.Destroy(); AudioRendererManager.Dispose(); KernelContext.Dispose(); } }
protected virtual void Dispose(bool disposing) { if (!_isDisposed && disposing) { ConfigurationState.Instance.System.EnableDockedMode.Event -= OnDockedModeChange; _isDisposed = true; SurfaceFlinger.Dispose(); KProcess terminationProcess = new KProcess(KernelContext); KThread terminationThread = new KThread(KernelContext); terminationThread.Initialize(0, 0, 0, 3, 0, terminationProcess, ThreadType.Kernel, () => { // Force all threads to exit. lock (KernelContext.Processes) { foreach (KProcess process in KernelContext.Processes.Values) { process.Terminate(); } } // Exit ourself now! KernelContext.Scheduler.ExitThread(terminationThread); KernelContext.Scheduler.GetCurrentThread().Exit(); KernelContext.Scheduler.RemoveThread(terminationThread); }); terminationThread.Start(); // Destroy nvservices channels as KThread could be waiting on some user events. // This is safe as KThread that are likely to call ioctls are going to be terminated by the post handler hook on the SVC facade. INvDrvServices.Destroy(); // This is needed as the IPC Dummy KThread is also counted in the ThreadCounter. KernelContext.ThreadCounter.Signal(); // It's only safe to release resources once all threads // have exited. KernelContext.ThreadCounter.Signal(); KernelContext.ThreadCounter.Wait(); AudioRendererManager.Dispose(); KernelContext.Dispose(); } }
protected virtual void Dispose(bool Disposing) { if (Disposing && !Disposed) { if (NeedsHbAbi && Executables[0].FilePath.EndsWith(Homebrew.TemporaryNroSuffix)) { File.Delete(Executables[0].FilePath); } //If there is still some thread running, disposing the objects is not //safe as the thread may try to access those resources. Instead, we set //the flag to have the Process disposed when all threads finishes. //Note: This may not happen if the guest code gets stuck on a infinite loop. if (TlsSlots.Count > 0) { ShouldDispose = true; Ns.Log.PrintInfo(LogClass.Loader, $"Process {ProcessId} waiting all threads terminate..."); return; } Disposed = true; foreach (object Obj in HandleTable.Clear()) { if (Obj is KSession Session) { Session.Dispose(); } } INvDrvServices.UnloadProcess(this); AppletState.Dispose(); SvcHandler.Dispose(); Memory.Dispose(); Ns.Log.PrintInfo(LogClass.Loader, $"Process {ProcessId} exiting..."); } }
private void Unload() { if (Disposed || Threads.Count > 0) { return; } Disposed = true; HandleTable.Destroy(); INvDrvServices.UnloadProcess(this); if (NeedsHbAbi && Executables.Count > 0 && Executables[0].FilePath.EndsWith(Homebrew.TemporaryNroSuffix)) { File.Delete(Executables[0].FilePath); } Logger.PrintInfo(LogClass.Loader, $"Process {ProcessId} exiting..."); }
protected virtual void Dispose(bool disposing) { if (!_isDisposed && disposing) { _isDisposed = true; // "Soft" stops AudioRenderer and AudioManager to avoid some sound between resume and stop. if (IsPaused) { AudioManager.StopUpdates(); TogglePauseEmulation(false); AudioRendererManager.StopSendingCommands(); } KProcess terminationProcess = new KProcess(KernelContext); KThread terminationThread = new KThread(KernelContext); terminationThread.Initialize(0, 0, 0, 3, 0, terminationProcess, ThreadType.Kernel, () => { // Force all threads to exit. lock (KernelContext.Processes) { // Terminate application. foreach (KProcess process in KernelContext.Processes.Values.Where(x => x.Flags.HasFlag(ProcessCreationFlags.IsApplication))) { process.Terminate(); process.DecrementReferenceCount(); } // The application existed, now surface flinger can exit too. SurfaceFlinger.Dispose(); // Terminate HLE services (must be done after the application is already terminated, // otherwise the application will receive errors due to service termination). foreach (KProcess process in KernelContext.Processes.Values.Where(x => !x.Flags.HasFlag(ProcessCreationFlags.IsApplication))) { process.Terminate(); process.DecrementReferenceCount(); } KernelContext.Processes.Clear(); } // Exit ourself now! KernelStatic.GetCurrentThread().Exit(); }); terminationThread.Start(); // Wait until the thread is actually started. while (terminationThread.HostThread.ThreadState == ThreadState.Unstarted) { Thread.Sleep(10); } // Wait until the termination thread is done terminating all the other threads. terminationThread.HostThread.Join(); // Destroy nvservices channels as KThread could be waiting on some user events. // This is safe as KThread that are likely to call ioctls are going to be terminated by the post handler hook on the SVC facade. INvDrvServices.Destroy(); AudioManager.Dispose(); AudioOutputManager.Dispose(); AudioInputManager.Dispose(); AudioRendererManager.Dispose(); LibHacHorizonManager.AmClient.Fs.UnregisterProgram(LibHacHorizonManager.ApplicationClient.Os.GetCurrentProcessId().Value); KernelContext.Dispose(); } }