a hack to unconditionally kill ffmpeg when parent .NET process exits

Former-commit-id: 5ac61011c4
This commit is contained in:
Victor Nova 2022-05-23 10:42:19 -07:00 committed by Malte Rosenbjerg
parent 0d7bf18832
commit 28deedc038
3 changed files with 61 additions and 1 deletions

46
FFMpegCore/Extend/Job.cs Normal file
View file

@ -0,0 +1,46 @@
using System;
using System.Runtime.InteropServices;
using static PInvoke.Kernel32;
namespace FFMpegCore.Extend {
public class Job : IDisposable {
readonly SafeObjectHandle handle;
public Job() {
this.handle = CreateJobObject(IntPtr.Zero, null);
var info = new JOBOBJECT_BASIC_LIMIT_INFORMATION {
LimitFlags = JOB_OBJECT_LIMIT_FLAGS.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE,
};
var extendedInfo = new JOBOBJECT_EXTENDED_LIMIT_INFORMATION { BasicLimitInformation = info };
int length = Marshal.SizeOf(typeof(JOBOBJECT_EXTENDED_LIMIT_INFORMATION));
IntPtr extendedInfoPtr = Marshal.AllocHGlobal(length);
Marshal.StructureToPtr(extendedInfo, extendedInfoPtr, false);
if (!SetInformationJobObject(this.handle, JOBOBJECTINFOCLASS.JobObjectExtendedLimitInformation, extendedInfoPtr, (uint)length))
throw new System.ComponentModel.Win32Exception();
}
public bool AddProcess(SafeObjectHandle processHandle) {
return AssignProcessToJobObject(this.handle, processHandle);
}
#region IDisposable Members
public void Dispose() {
this.Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing) => this.Close();
public void Close() => this.handle.Close();
#endregion
}
}

View file

@ -9,6 +9,12 @@
using System.Threading;
using System.Threading.Tasks;
using FFMpegCore.Enums;
using FFMpegCore.Exceptions;
using FFMpegCore.Extend;
using FFMpegCore.Helpers;
using Instances;
using PInvoke;
namespace FFMpegCore
{
@ -141,7 +147,14 @@ private async Task<IProcessResult> Process(ProcessArguments processArguments, Ca
_ffMpegArguments.Pre();
using var instance = processArguments.Start();
using var instance = (ProcessInstance)processArguments.Start();
using var job = new Job();
var processHack = (Process)typeof(ProcessInstance).GetField("_process", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance)
.GetValue(instance);
using var instanceHandle = new Kernel32.SafeObjectHandle(processHack.Handle, ownsHandle: false);
job.AddProcess(instanceHandle);
var cancelled = false;
void OnCancelEvent(object sender, int timeout)
{

View file

@ -17,6 +17,7 @@
<ItemGroup>
<PackageReference Include="Instances" Version="3.0.0"/>
<PackageReference Include="PInvoke.Kernel32" Version="0.7.104" />
<PackageReference Include="System.Text.Json" Version="7.0.1"/>
</ItemGroup>