private bool IsExternalProcessAlive() { lock (this.acquisitionLock) { if (this.isHeldInternally) { if (this.lockHolder != null) { throw new InvalidOperationException("Inconsistent GVFSLock state with external holder " + this.lockHolder.ToString()); } return(false); } if (this.lockHolder == null) { return(false); } Process process; if (ProcessHelper.TryGetProcess(this.lockHolder.PID, out process) && string.Equals(this.lockHolder.OriginalCommand, ProcessHelper.GetCommandLine(process))) { return(true); } this.ClearHolder(); return(false); } }
public void WatchForTermination(int pid) { lock (this.terminationLock) { this.pendingPid = pid; this.currentPid = null; this.watcher.Query = new EventQuery("WQL", string.Format(QueryTemplate, this.pendingPid)); } // Start the watch async since it takes > 100ms and there's no need to make the client wait. Task.Run(() => { lock (this.terminationLock) { if (this.pendingPid != null) { Process process; if (ProcessHelper.TryGetProcess(this.pendingPid.Value, out process) && this.ShouldWatchProcess(process)) { this.watcher.Start(); this.currentPid = this.pendingPid; } else { this.onProcessTerminated(this.pendingPid.Value); } this.pendingPid = null; } } }); }
public bool IsExternalLockHolderAlive() { lock (this.acquisitionLock) { if (this.lockHolder == null) { return(false); } Process process = null; try { int pid = this.lockHolder.PID; if (ProcessHelper.TryGetProcess(pid, out process)) { return(true); } this.ReleaseLockForTerminatedProcess(pid); return(false); } finally { if (process != null) { process.Dispose(); } } } }
public void WatchForTermination(int pid, string expectedExeNamePrefix) { lock (this.terminationLock) { this.pendingPid = pid; this.currentPid = null; this.watcher.Query = new EventQuery("WQL", string.Format(QueryTemplate, this.pendingPid)); } // Start the watch async since it takes > 100ms and there's no need to make the client wait. Task.Run(() => { lock (this.terminationLock) { if (this.pendingPid != null) { Process process; if (ProcessHelper.TryGetProcess(this.pendingPid.Value, out process) && process.MainModule.ModuleName.StartsWith(expectedExeNamePrefix, StringComparison.OrdinalIgnoreCase) && process.MainModule.ModuleName.EndsWith(GVFSConstants.ExecutableExtension, StringComparison.OrdinalIgnoreCase)) { this.watcher.Start(); this.currentPid = this.pendingPid; } else { this.onProcessTerminated(this.pendingPid.Value); } this.pendingPid = null; } } }); }
/// <summary> /// Allows external callers (non-GVFS) to acquire the lock. /// </summary> /// <param name="requester">The data for the external acquisition request.</param> /// <param name="holder"> /// The current holder of the lock if the acquisition fails, or /// the input request if it succeeds. /// </param> /// <returns>True if the lock was acquired, false otherwise.</returns> public bool TryAcquireLock( NamedPipeMessages.AcquireLock.Data requester, out NamedPipeMessages.AcquireLock.Data holder) { EventMetadata metadata = new EventMetadata(); EventLevel eventLevel = EventLevel.Verbose; metadata.Add("LockRequest", requester.ToString()); try { lock (this.acquisitionLock) { if (this.isHeldInternally) { holder = null; metadata.Add("CurrentLockHolder", "GVFS"); metadata.Add("Result", "Denied"); return(false); } if (this.IsExternalProcessAlive() && this.lockHolder.PID != requester.PID) { holder = this.lockHolder; metadata.Add("CurrentLockHolder", this.lockHolder.ToString()); metadata.Add("Result", "Denied"); return(false); } metadata.Add("Result", "Accepted"); eventLevel = EventLevel.Informational; Process process; if (ProcessHelper.TryGetProcess(requester.PID, out process) && string.Equals(requester.OriginalCommand, ProcessHelper.GetCommandLine(process))) { this.lockHolder = requester; holder = requester; return(true); } else { // Process is no longer running so let it // succeed since the process non-existence // signals the lock release. holder = null; return(true); } } } finally { this.tracer.RelatedEvent(eventLevel, "TryAcquireLockExternal", metadata); } }
public bool IsLockAvailable(bool checkExternalHolderOnly = false) { lock (this.acquisitionLock) { if (!checkExternalHolderOnly && this.isLockedByGVFS) { return(false); } if (this.externalLockHolder == null) { return(true); } Process process = null; try { int pid = this.externalLockHolder.PID; if (ProcessHelper.TryGetProcess(pid, out process)) { return(false); } this.ReleaseLockForTerminatedProcess(pid); return(true); } finally { if (process != null) { process.Dispose(); } } } }
/// <summary> /// Allows external callers (non-GVFS) to acquire the lock. /// </summary> /// <param name="requester">The data for the external acquisition request.</param> /// <param name="holder"> /// The current holder of the lock if the acquisition fails, or /// the input request if it succeeds. /// </param> /// <returns>True if the lock was acquired, false otherwise.</returns> public bool TryAcquireLock( NamedPipeMessages.LockData requester, out NamedPipeMessages.LockData holder) { EventMetadata metadata = new EventMetadata(); EventLevel eventLevel = EventLevel.Verbose; metadata.Add("LockRequest", requester.ToString()); try { lock (this.acquisitionLock) { if (this.IsLockedByGVFS) { holder = null; metadata.Add("CurrentLockHolder", "GVFS"); metadata.Add("Result", "Denied"); return(false); } if (this.lockHolder != null && this.lockHolder.PID != requester.PID) { holder = this.lockHolder; metadata.Add("CurrentLockHolder", this.lockHolder.ToString()); metadata.Add("Result", "Denied"); return(false); } metadata.Add("Result", "Accepted"); eventLevel = EventLevel.Informational; Process process; if (ProcessHelper.TryGetProcess(requester.PID, out process)) { this.processWatcher.WatchForTermination(requester.PID, GVFSConstants.CommandParentExecutableNames); process.Dispose(); this.lockHolder = requester; holder = requester; this.externalLockReleased.Reset(); return(true); } else { // Process is no longer running so let it // succeed since the process non-existence // signals the lock release. if (process != null) { process.Dispose(); } holder = null; return(true); } } } finally { this.tracer.RelatedEvent(eventLevel, "TryAcquireLockExternal", metadata); } }