public HttpResponse Handle(HttpRequest req) { Interlocked.Increment(ref _activeConnections); try { // Must call the handle method first because this is a call across the AppDomain boundary return(RunnerProxy.Handle(req)); } finally { // THEN add the callback, which would otherwise not be serializable req.CleanUpCallback += () => { Interlocked.Decrement(ref _activeConnections); }; } }
private static int _appDomainCount = 0; // only used to give each AppDomain a unique name public AppDomainInfo(LoggerBase log, PropellerSettings settings, PropellerModuleSettings moduleSettings, ISettingsSaver saver) { ModuleSettings = moduleSettings; Saver = saver; _log = log; _activeConnections = 0; // Determine the temporary folder that DLLs will be copied to var tempFolder = settings.TempFolder ?? Path.GetTempPath(); Directory.CreateDirectory(tempFolder); // Find a new folder to put the DLL/EXE files into int j = 1; do { TempPathUsed = Path.Combine(tempFolder, "propeller-tmp-" + (j++)); }while (Directory.Exists(TempPathUsed)); Directory.CreateDirectory(TempPathUsed); // Copy all the DLLs/EXEs to the temporary folder foreach (var sourceFile in new[] { typeof(PropellerEngine), typeof(IPropellerModule), typeof(HttpServer), typeof(Ut) }.Select(type => type.Assembly.Location).Concat( new[] { "*.exe", "*.dll", "*.pdb" }.SelectMany(ext => Directory.EnumerateFiles(Path.GetDirectoryName(moduleSettings.ModuleDll), ext)))) { var destFile = Path.Combine(TempPathUsed, Path.GetFileName(sourceFile)); if (File.Exists(destFile)) { _log.Warn(2, "Skipping file {0} because destination file {1} already exists.".Fmt(sourceFile, destFile)); } else { _log.Info(2, "Copying file {0} to {1}".Fmt(sourceFile, destFile)); File.Copy(sourceFile, destFile); } } // Create an AppDomain var setup = new AppDomainSetup { ApplicationBase = TempPathUsed, PrivateBinPath = TempPathUsed }; AppDomain = AppDomain.CreateDomain("Propeller AppDomain #{0}, module {1}".Fmt(_appDomainCount++, moduleSettings.ModuleName), null, setup); RunnerProxy = (AppDomainRunner)AppDomain.CreateInstanceAndUnwrap("Propeller", "RT.Propeller.AppDomainRunner"); RunnerProxy.Init( Path.Combine(TempPathUsed, Path.GetFileName(moduleSettings.ModuleDll)), moduleSettings.ModuleType, moduleSettings.ModuleName, moduleSettings.Settings, _log, saver); IEnumerable <string> filters = moduleSettings.MonitorFilters ?? Enumerable.Empty <string>(); if (RunnerProxy.FileFiltersToBeMonitoredForChanges != null) { filters = filters.Concat(RunnerProxy.FileFiltersToBeMonitoredForChanges); } foreach (var filter in filters.Concat(moduleSettings.ModuleDll)) { addFileSystemWatcher(Path.GetDirectoryName(filter), Path.GetFileName(filter)); } UrlMappings = moduleSettings.Hooks.Select(hook => new UrlMapping(hook, Handle, true)).ToArray(); _log.Info("Module {0} URLs: {1}".Fmt(moduleSettings.ModuleName, moduleSettings.Hooks.JoinString("; "))); }