Пример #1
0
        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);
            }
        }
Пример #2
0
        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;
                    }
                }
            });
        }
Пример #3
0
        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();
                    }
                }
            }
        }
Пример #4
0
        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;
                    }
                }
            });
        }
Пример #5
0
        /// <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);
            }
        }
Пример #6
0
        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();
                    }
                }
            }
        }
Пример #7
0
        /// <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);
            }
        }