Skip to content

Commit 9f05280

Browse files
committed
added a timeout to the T4 host process so it will self terminate after x seconds of in activity
1 parent 1b4781c commit 9f05280

File tree

8 files changed

+66
-124
lines changed

8 files changed

+66
-124
lines changed

Forms/TemplatingHostOptionsPageGrid.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,11 @@ public string CompilerOptions
4747
// set => runtimeKind = value;
4848
//}
4949

50+
[Category(Package.SubSonicCoreCategory)]
51+
[DisplayName("Host Execution Timeout")]
52+
[Description("Length of time the host will wait for activity before shutting down, in seconds.")]
53+
public int Timeout { get; } = 120;
54+
5055
private bool linePragmas = true;
5156

5257
[Category(Package.SubSonicCoreCategory)]

Services/SubSonicTemplatingService/SubSonicTemplatingService.cs

Lines changed: 1 addition & 110 deletions
Original file line numberDiff line numberDiff line change
@@ -247,121 +247,12 @@ public async Task<string> ResolveAssemblyReferenceAsync(string assemblyReference
247247
}
248248
}
249249
}
250-
}
251-
252-
// if not found look at the project references
253-
//if (!foundAssembly.IsMatch(path))
254-
//{
255-
// // not sure if this willl be a problem, I worry about reference only assemblies.
256-
// // maybe ensure that the reference is from the nuget package and is a real boy.
257-
// // second check the project references
258-
// if (Package()?.GetService<DTE>() is DTE dTE)
259-
// {
260-
// foreach (Project project in dTE.Solution.Projects)
261-
// {
262-
// if (project.Object is VSProject vsProject)
263-
// {
264-
// path = ResolveAssemblyReferenceByProject(assemblyReference, vsProject.References, GlobalAssemblyCacheHelper.strongNameRegEx.Match(assemblyReference));
265-
// }
266-
// else if (project.Object is VsWebSite.VSWebSite vsWebSite)
267-
// {
268-
// path = ResolveAssemblyReferenceByProject(assemblyReference, vsWebSite.References, GlobalAssemblyCacheHelper.strongNameRegEx.Match(assemblyReference));
269-
// }
270-
// }
271-
// }
272-
//}
250+
}
273251
}
274252

275253
return path;
276254
}
277255

278-
//private string ResolveAssemblyReferenceByProject(string assemblyReference, References references, Match assembly)
279-
//{
280-
// foreach (Reference reference in references)
281-
// {
282-
// if (!assembly.Success && reference.Name.Equals(assemblyReference, StringComparison.OrdinalIgnoreCase))
283-
// { // found the reference
284-
// if (VerifyAssemblyValidity(reference.Path, out string path))
285-
// {
286-
// return path;
287-
// }
288-
// continue;
289-
// }
290-
// else if (reference.Name.Equals(assembly.Groups["name"].Value, StringComparison.OrdinalIgnoreCase) &&
291-
// Version.Parse(reference.Version) >= Version.Parse(assembly.Groups["version"].Value))
292-
// {
293-
// if (VerifyAssemblyValidity(reference.Path, out string path))
294-
// {
295-
// return path;
296-
// }
297-
// continue;
298-
// }
299-
// }
300-
301-
// return assemblyReference;
302-
//}
303-
304-
//private string ResolveAssemblyReferenceByProject(string assemblyReference, VsWebSite.AssemblyReferences references, Match assembly)
305-
//{
306-
// foreach (VsWebSite.AssemblyReference reference in references)
307-
// {
308-
// if (!assembly.Success && reference.Name.Equals(assemblyReference, StringComparison.OrdinalIgnoreCase))
309-
// { // found the reference
310-
// if (VerifyAssemblyValidity(reference.FullPath, out string path))
311-
// {
312-
// return path;
313-
// }
314-
// continue;
315-
// }
316-
// else if (reference.StrongName.Equals(assembly.Groups["name"].Value, StringComparison.OrdinalIgnoreCase))
317-
// {
318-
// if (VerifyAssemblyValidity(reference.FullPath, out string path))
319-
// {
320-
// return path;
321-
// }
322-
// continue;
323-
// }
324-
// }
325-
326-
// return assemblyReference;
327-
//}
328-
329-
//private bool VerifyAssemblyValidity(string path, out string assemblyPath)
330-
//{
331-
// assemblyPath = path;
332-
333-
// if (assemblyPath.Contains("\\ref\\"))
334-
// { // strong possibility that this is a reference assembly
335-
// // banking on path structure being logical and in line with package build guidelines.
336-
337-
// int index = assemblyPath.IndexOf("\\ref\\");
338-
// string[] _path = new[]
339-
// {
340-
// assemblyPath.Substring(0, index),
341-
// assemblyPath.Substring(index + "\\ref\\".Length)
342-
// };
343-
344-
// if (Directory.Exists(Path.Combine(_path[0],"runtimes")))
345-
// {
346-
// if (Environment.OSVersion.Platform == PlatformID.Win32NT)
347-
// {
348-
// assemblyPath = Path.Combine(_path[0], "runtimes\\win\\lib", _path[1]);
349-
// }
350-
// else if (Environment.OSVersion.Platform == PlatformID.Unix)
351-
// {
352-
// assemblyPath = Path.Combine(_path[0], "runtimes\\unix\\lib", _path[1]);
353-
// }
354-
// }
355-
// else
356-
// {
357-
// assemblyPath = assemblyPath.Replace("\\ref\\", "\\lib\\");
358-
// }
359-
360-
// return File.Exists(assemblyPath);
361-
// }
362-
// return true;
363-
//}
364-
365256
private string GetVSInstallDir(RegistryKey applicationRoot)
366257
{
367258
string str = string.Empty;

Services/SubSonicTemplatingService/TextTemplating.cs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,7 @@ private async ThreadingTasks.Task<IProcessTransformationRunFactory> GetTransform
505505
throw new FileNotFoundException(SubSonicCoreErrors.FileNotFound, SubSonicMenuCommands.SubSonicHostProcessFileName);
506506
}
507507

508-
Guid guid = Guid.NewGuid();
509-
510-
ProcessStartInfo psi = new ProcessStartInfo(path, guid.ToString())
508+
ProcessStartInfo psi = new ProcessStartInfo(path, SubSonicCoreVisualStudioCommonResources.HostArgumentString.Format(TransformationRunFactory.TransformationRunFactoryService, Package().HostOptions.Timeout))
511509
{
512510
CreateNoWindow = true,
513511
UseShellExecute = false,

SubSonic.Core.VisualStudio.Common/SubSonic.Core.VisualStudio.Common.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
<PackageReference Include="Mono.TextTemplating" Version="2.2.0-preview-0171-g166965ae2b" />
1313
<PackageReference Include="NuGet.Configuration" Version="5.7.0" />
1414
<PackageReference Include="SubSonic.Core.Extensions" Version="1.1.0" />
15-
<PackageReference Include="SubSonic.Core.Remoting" Version="1.0.0-preview-0051-g6c481c84e7" />
15+
<PackageReference Include="SubSonic.Core.Remoting" Version="1.0.0-preview-0052-g38edfd749c" />
1616
<PackageReference Include="System.CodeDom" Version="4.7.0" />
1717
<PackageReference Condition="'$(TargetFramework)'=='netstandard2.0' OR '$(TargetFramework)'=='netcoreapp3.1'" Include="System.Runtime.Loader" Version="4.3.0" />
1818
</ItemGroup>
@@ -41,7 +41,7 @@
4141

4242
<ItemGroup>
4343
<EmbeddedResource Update="SubSonicCoreVisualStudioCommonResources.resx">
44-
<Generator>ResXFileCodeGenerator</Generator>
44+
<Generator>PublicResXFileCodeGenerator</Generator>
4545
<LastGenOutput>SubSonicCoreVisualStudioCommonResources.Designer.cs</LastGenOutput>
4646
</EmbeddedResource>
4747
</ItemGroup>

SubSonic.Core.VisualStudio.Common/SubSonic.Core.VisualStudio.Host/TransformationRunFactoryService.cs

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,23 @@ public class TransformationRunFactoryService
1818

1919
[NonSerialized]
2020
private readonly IProcessTransformationRunFactory runFactory;
21+
private DateTime lastUsed;
22+
private readonly int timeout;
2123

22-
public TransformationRunFactoryService(Uri serviceUri)
24+
public TransformationRunFactoryService(Uri serviceUri, int timeout)
2325
: base(serviceUri)
2426
{
27+
this.timeout = timeout;
28+
lastUsed = DateTime.Now;
2529
runFactory = new RemoteTransformationRunFactory(Guid.NewGuid());
2630
}
2731

32+
public override bool IsRunning
33+
{
34+
get => (base.IsRunning && (lastUsed.AddSeconds(timeout) > DateTime.Now));
35+
protected set => base.IsRunning = value;
36+
}
37+
2838
public Guid GetFactoryId()
2939
{
3040
return runFactory.GetFactoryId();
@@ -44,6 +54,8 @@ public IProcessTransformationRunner CreateTransformationRunner()
4454
{
4555
try
4656
{
57+
lastUsed = DateTime.Now;
58+
4759
IProcessTransformationRunner runner = runFactory.CreateTransformationRunner();
4860

4961
Console.Out.WriteLine(SubSonicCoreVisualStudioCommonResources.CreatedTransformationRunner.Format(runner.RunnerId, runner.GetType().FullName));
@@ -78,6 +90,8 @@ public bool PrepareTransformation(Guid runnerId, ParsedTemplate pt, string conte
7890
{
7991
try
8092
{
93+
lastUsed = DateTime.Now;
94+
8195
return runFactory.PrepareTransformation(runnerId, pt, content, host, settings);
8296
}
8397
catch(Exception ex)
@@ -91,6 +105,8 @@ public ITextTemplatingCallback StartTransformation(Guid runnerId)
91105
{
92106
try
93107
{
108+
lastUsed = DateTime.Now;
109+
94110
ITextTemplatingCallback result = runFactory.StartTransformation(runnerId);
95111

96112
if (result.Errors.HasErrors)
@@ -116,6 +132,8 @@ public ITextTemplatingCallback StartTransformation(Guid runnerId)
116132

117133
public TemplateErrorCollection GetErrors(Guid runnerId)
118134
{
135+
lastUsed = DateTime.Now;
136+
119137
return runFactory.GetErrors(runnerId);
120138
}
121139

SubSonic.Core.VisualStudio.Common/SubSonicCoreVisualStudioCommonResources.Designer.cs

Lines changed: 15 additions & 6 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

SubSonic.Core.VisualStudio.Common/SubSonicCoreVisualStudioCommonResources.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,9 @@
123123
<data name="DisposedTransformationRunner" xml:space="preserve">
124124
<value>disposed runner [{0}]</value>
125125
</data>
126+
<data name="HostArgumentString" xml:space="preserve">
127+
<value>pipename:{0} timeout:{1}</value>
128+
</data>
126129
<data name="MethodIsStubbedOutForProxyImpersonation" xml:space="preserve">
127130
<value>Method is not meant to be executed server side.</value>
128131
</data>

SubSonic.Core.VisualStudio.HostProcess/Program.cs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,21 +17,39 @@ static void Main(string[] args)
1717
var logger = new Logger(logLevel: LogLevel.Debug);
1818
var stats = new Stats();
1919

20-
var pipename = TransformationRunFactory.TransformationRunFactoryService;
20+
string pipename = TransformationRunFactory.TransformationRunFactoryService;
21+
int timeout = 60;
22+
23+
foreach(string arg in args)
24+
{
25+
if (arg.StartsWith(nameof(pipename), StringComparison.OrdinalIgnoreCase))
26+
{
27+
pipename = arg.Split(':')[1];
28+
}
29+
else if (arg.StartsWith(nameof(timeout), StringComparison.OrdinalIgnoreCase) &&
30+
int.TryParse(arg.Split(':')[1], out int _timeout))
31+
{
32+
timeout = _timeout;
33+
}
34+
}
2135

2236
#pragma warning disable IDE0063 // Use simple 'using' statement
23-
using (TransformationRunFactoryService service = new TransformationRunFactoryService(new Uri($"ipc://{TransformationRunFactory.TransformationRunFactoryService}")))
37+
using (TransformationRunFactoryService service = new TransformationRunFactoryService(new Uri($"ipc://{pipename}"), timeout))
2438
#pragma warning restore IDE0063 // Use simple 'using' statement
2539
using (NpHost host = new NpHost(pipename, logger, stats))
2640
{
2741
host.AddService<ITransformationRunFactoryService>(service);
2842

2943
host.Open();
3044

45+
Console.Out.WriteLine($"Startup: {DateTime.Now}");
46+
3147
while(service.IsRunning)
3248
{
3349
Thread.Sleep(10);
3450
}
51+
52+
Console.Out.WriteLine($"Shutdown: {DateTime.Now}");
3553
}
3654
}
3755
}

0 commit comments

Comments
 (0)