History

Renamed folders and separated GSF.Media and GSF.Net into separate projects.

StephenCWills committed 14 years ago

Commit ac1ef661 parent 45bce55628 files · +733 −461Browse files

Showing the changes to Source/Libraries/GSF.Core/Threading/InterprocessLock.cs (1 of 628 files). Show all

Unified · Split

Source/Libraries/GSF.Core/Threading/InterprocessLock.cs+522−0
@@ -0,0 +1,522 @@
1+//*******************************************************************************************************
2+// InterprocessLock.cs - Gbtc
3+//
4+// Tennessee Valley Authority, 2011
5+// No copyright is claimed pursuant to 17 USC § 105. All Other Rights Reserved.
6+//
7+// This software is made freely available under the TVA Open Source Agreement (see below).
8+// Code in this file licensed to GSF under one or more contributor license agreements listed below.
9+//
10+// Code Modification History:
11+// -----------------------------------------------------------------------------------------------------
12+// 03/21/2011 - J. Ritchie Carroll
13+// Generated original version of source code.
14+// 06/30/2011 - Stephen Wills
15+// Applying changes from Jian (Ryan) Zuo: updated to allow unauthorized users to attempt to grant
16+// themselves lower than full access to existing mutexes and semaphores.
17+// 08/12/2011 - J. Ritchie Carroll
18+// Modified creation methods such that locking natives are created in a synchronized fashion.
19+// 09/21/2011 - J. Ritchie Carroll
20+// Added Mono implementation exception regions.
21+//
22+//*******************************************************************************************************
23+
24+#region [ TVA Open Source Agreement ]
25+/*
26+
27+ THIS OPEN SOURCE AGREEMENT ("AGREEMENT") DEFINES THE RIGHTS OF USE,REPRODUCTION, DISTRIBUTION,
28+ MODIFICATION AND REDISTRIBUTION OF CERTAIN COMPUTER SOFTWARE ORIGINALLY RELEASED BY THE
29+ TENNESSEE VALLEY AUTHORITY, A CORPORATE AGENCY AND INSTRUMENTALITY OF THE UNITED STATES GOVERNMENT
30+ ("GOVERNMENT AGENCY"). GOVERNMENT AGENCY IS AN INTENDED THIRD-PARTY BENEFICIARY OF ALL SUBSEQUENT
31+ DISTRIBUTIONS OR REDISTRIBUTIONS OF THE SUBJECT SOFTWARE. ANYONE WHO USES, REPRODUCES, DISTRIBUTES,
32+ MODIFIES OR REDISTRIBUTES THE SUBJECT SOFTWARE, AS DEFINED HEREIN, OR ANY PART THEREOF, IS, BY THAT
33+ ACTION, ACCEPTING IN FULL THE RESPONSIBILITIES AND OBLIGATIONS CONTAINED IN THIS AGREEMENT.
34+
35+ Original Software Designation: openPDC
36+ Original Software Title: The GSF Open Source Phasor Data Concentrator
37+ User Registration Requested. Please Visit https://naspi.tva.com/Registration/
38+ Point of Contact for Original Software: J. Ritchie Carroll <mailto:jrcarrol@tva.gov>
39+
40+ 1. DEFINITIONS
41+
42+ A. "Contributor" means Government Agency, as the developer of the Original Software, and any entity
43+ that makes a Modification.
44+
45+ B. "Covered Patents" mean patent claims licensable by a Contributor that are necessarily infringed by
46+ the use or sale of its Modification alone or when combined with the Subject Software.
47+
48+ C. "Display" means the showing of a copy of the Subject Software, either directly or by means of an
49+ image, or any other device.
50+
51+ D. "Distribution" means conveyance or transfer of the Subject Software, regardless of means, to
52+ another.
53+
54+ E. "Larger Work" means computer software that combines Subject Software, or portions thereof, with
55+ software separate from the Subject Software that is not governed by the terms of this Agreement.
56+
57+ F. "Modification" means any alteration of, including addition to or deletion from, the substance or
58+ structure of either the Original Software or Subject Software, and includes derivative works, as that
59+ term is defined in the Copyright Statute, 17 USC § 101. However, the act of including Subject Software
60+ as part of a Larger Work does not in and of itself constitute a Modification.
61+
62+ G. "Original Software" means the computer software first released under this Agreement by Government
63+ Agency entitled openPDC, including source code, object code and accompanying documentation, if any.
64+
65+ H. "Recipient" means anyone who acquires the Subject Software under this Agreement, including all
66+ Contributors.
67+
68+ I. "Redistribution" means Distribution of the Subject Software after a Modification has been made.
69+
70+ J. "Reproduction" means the making of a counterpart, image or copy of the Subject Software.
71+
72+ K. "Sale" means the exchange of the Subject Software for money or equivalent value.
73+
74+ L. "Subject Software" means the Original Software, Modifications, or any respective parts thereof.
75+
76+ M. "Use" means the application or employment of the Subject Software for any purpose.
77+
78+ 2. GRANT OF RIGHTS
79+
80+ A. Under Non-Patent Rights: Subject to the terms and conditions of this Agreement, each Contributor,
81+ with respect to its own contribution to the Subject Software, hereby grants to each Recipient a
82+ non-exclusive, world-wide, royalty-free license to engage in the following activities pertaining to
83+ the Subject Software:
84+
85+ 1. Use
86+
87+ 2. Distribution
88+
89+ 3. Reproduction
90+
91+ 4. Modification
92+
93+ 5. Redistribution
94+
95+ 6. Display
96+
97+ B. Under Patent Rights: Subject to the terms and conditions of this Agreement, each Contributor, with
98+ respect to its own contribution to the Subject Software, hereby grants to each Recipient under Covered
99+ Patents a non-exclusive, world-wide, royalty-free license to engage in the following activities
100+ pertaining to the Subject Software:
101+
102+ 1. Use
103+
104+ 2. Distribution
105+
106+ 3. Reproduction
107+
108+ 4. Sale
109+
110+ 5. Offer for Sale
111+
112+ C. The rights granted under Paragraph B. also apply to the combination of a Contributor's Modification
113+ and the Subject Software if, at the time the Modification is added by the Contributor, the addition of
114+ such Modification causes the combination to be covered by the Covered Patents. It does not apply to
115+ any other combinations that include a Modification.
116+
117+ D. The rights granted in Paragraphs A. and B. allow the Recipient to sublicense those same rights.
118+ Such sublicense must be under the same terms and conditions of this Agreement.
119+
120+ 3. OBLIGATIONS OF RECIPIENT
121+
122+ A. Distribution or Redistribution of the Subject Software must be made under this Agreement except for
123+ additions covered under paragraph 3H.
124+
125+ 1. Whenever a Recipient distributes or redistributes the Subject Software, a copy of this Agreement
126+ must be included with each copy of the Subject Software; and
127+
128+ 2. If Recipient distributes or redistributes the Subject Software in any form other than source code,
129+ Recipient must also make the source code freely available, and must provide with each copy of the
130+ Subject Software information on how to obtain the source code in a reasonable manner on or through a
131+ medium customarily used for software exchange.
132+
133+ B. Each Recipient must ensure that the following copyright notice appears prominently in the Subject
134+ Software:
135+
136+ No copyright is claimed pursuant to 17 USC § 105. All Other Rights Reserved.
137+
138+ C. Each Contributor must characterize its alteration of the Subject Software as a Modification and
139+ must identify itself as the originator of its Modification in a manner that reasonably allows
140+ subsequent Recipients to identify the originator of the Modification. In fulfillment of these
141+ requirements, Contributor must include a file (e.g., a change log file) that describes the alterations
142+ made and the date of the alterations, identifies Contributor as originator of the alterations, and
143+ consents to characterization of the alterations as a Modification, for example, by including a
144+ statement that the Modification is derived, directly or indirectly, from Original Software provided by
145+ Government Agency. Once consent is granted, it may not thereafter be revoked.
146+
147+ D. A Contributor may add its own copyright notice to the Subject Software. Once a copyright notice has
148+ been added to the Subject Software, a Recipient may not remove it without the express permission of
149+ the Contributor who added the notice.
150+
151+ E. A Recipient may not make any representation in the Subject Software or in any promotional,
152+ advertising or other material that may be construed as an endorsement by Government Agency or by any
153+ prior Recipient of any product or service provided by Recipient, or that may seek to obtain commercial
154+ advantage by the fact of Government Agency's or a prior Recipient's participation in this Agreement.
155+
156+ F. In an effort to track usage and maintain accurate records of the Subject Software, each Recipient,
157+ upon receipt of the Subject Software, is requested to register with Government Agency by visiting the
158+ following website: https://naspi.tva.com/Registration/. Recipient's name and personal information
159+ shall be used for statistical purposes only. Once a Recipient makes a Modification available, it is
160+ requested that the Recipient inform Government Agency at the web site provided above how to access the
161+ Modification.
162+
163+ G. Each Contributor represents that that its Modification does not violate any existing agreements,
164+ regulations, statutes or rules, and further that Contributor has sufficient rights to grant the rights
165+ conveyed by this Agreement.
166+
167+ H. A Recipient may choose to offer, and to charge a fee for, warranty, support, indemnity and/or
168+ liability obligations to one or more other Recipients of the Subject Software. A Recipient may do so,
169+ however, only on its own behalf and not on behalf of Government Agency or any other Recipient. Such a
170+ Recipient must make it absolutely clear that any such warranty, support, indemnity and/or liability
171+ obligation is offered by that Recipient alone. Further, such Recipient agrees to indemnify Government
172+ Agency and every other Recipient for any liability incurred by them as a result of warranty, support,
173+ indemnity and/or liability offered by such Recipient.
174+
175+ I. A Recipient may create a Larger Work by combining Subject Software with separate software not
176+ governed by the terms of this agreement and distribute the Larger Work as a single product. In such
177+ case, the Recipient must make sure Subject Software, or portions thereof, included in the Larger Work
178+ is subject to this Agreement.
179+
180+ J. Notwithstanding any provisions contained herein, Recipient is hereby put on notice that export of
181+ any goods or technical data from the United States may require some form of export license from the
182+ U.S. Government. Failure to obtain necessary export licenses may result in criminal liability under
183+ U.S. laws. Government Agency neither represents that a license shall not be required nor that, if
184+ required, it shall be issued. Nothing granted herein provides any such export license.
185+
186+ 4. DISCLAIMER OF WARRANTIES AND LIABILITIES; WAIVER AND INDEMNIFICATION
187+
188+ A. No Warranty: THE SUBJECT SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY OF ANY KIND, EITHER
189+ EXPRESSED, IMPLIED, OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, ANY WARRANTY THAT THE SUBJECT
190+ SOFTWARE WILL CONFORM TO SPECIFICATIONS, ANY IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
191+ PARTICULAR PURPOSE, OR FREEDOM FROM INFRINGEMENT, ANY WARRANTY THAT THE SUBJECT SOFTWARE WILL BE ERROR
192+ FREE, OR ANY WARRANTY THAT DOCUMENTATION, IF PROVIDED, WILL CONFORM TO THE SUBJECT SOFTWARE. THIS
193+ AGREEMENT DOES NOT, IN ANY MANNER, CONSTITUTE AN ENDORSEMENT BY GOVERNMENT AGENCY OR ANY PRIOR
194+ RECIPIENT OF ANY RESULTS, RESULTING DESIGNS, HARDWARE, SOFTWARE PRODUCTS OR ANY OTHER APPLICATIONS
195+ RESULTING FROM USE OF THE SUBJECT SOFTWARE. FURTHER, GOVERNMENT AGENCY DISCLAIMS ALL WARRANTIES AND
196+ LIABILITIES REGARDING THIRD-PARTY SOFTWARE, IF PRESENT IN THE ORIGINAL SOFTWARE, AND DISTRIBUTES IT
197+ "AS IS."
198+
199+ B. Waiver and Indemnity: RECIPIENT AGREES TO WAIVE ANY AND ALL CLAIMS AGAINST GOVERNMENT AGENCY, ITS
200+ AGENTS, EMPLOYEES, CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT. IF RECIPIENT'S USE
201+ OF THE SUBJECT SOFTWARE RESULTS IN ANY LIABILITIES, DEMANDS, DAMAGES, EXPENSES OR LOSSES ARISING FROM
202+ SUCH USE, INCLUDING ANY DAMAGES FROM PRODUCTS BASED ON, OR RESULTING FROM, RECIPIENT'S USE OF THE
203+ SUBJECT SOFTWARE, RECIPIENT SHALL INDEMNIFY AND HOLD HARMLESS GOVERNMENT AGENCY, ITS AGENTS,
204+ EMPLOYEES, CONTRACTORS AND SUBCONTRACTORS, AS WELL AS ANY PRIOR RECIPIENT, TO THE EXTENT PERMITTED BY
205+ LAW. THE FOREGOING RELEASE AND INDEMNIFICATION SHALL APPLY EVEN IF THE LIABILITIES, DEMANDS, DAMAGES,
206+ EXPENSES OR LOSSES ARE CAUSED, OCCASIONED, OR CONTRIBUTED TO BY THE NEGLIGENCE, SOLE OR CONCURRENT, OF
207+ GOVERNMENT AGENCY OR ANY PRIOR RECIPIENT. RECIPIENT'S SOLE REMEDY FOR ANY SUCH MATTER SHALL BE THE
208+ IMMEDIATE, UNILATERAL TERMINATION OF THIS AGREEMENT.
209+
210+ 5. GENERAL TERMS
211+
212+ A. Termination: This Agreement and the rights granted hereunder will terminate automatically if a
213+ Recipient fails to comply with these terms and conditions, and fails to cure such noncompliance within
214+ thirty (30) days of becoming aware of such noncompliance. Upon termination, a Recipient agrees to
215+ immediately cease use and distribution of the Subject Software. All sublicenses to the Subject
216+ Software properly granted by the breaching Recipient shall survive any such termination of this
217+ Agreement.
218+
219+ B. Severability: If any provision of this Agreement is invalid or unenforceable under applicable law,
220+ it shall not affect the validity or enforceability of the remainder of the terms of this Agreement.
221+
222+ C. Applicable Law: This Agreement shall be subject to United States federal law only for all purposes,
223+ including, but not limited to, determining the validity of this Agreement, the meaning of its
224+ provisions and the rights, obligations and remedies of the parties.
225+
226+ D. Entire Understanding: This Agreement constitutes the entire understanding and agreement of the
227+ parties relating to release of the Subject Software and may not be superseded, modified or amended
228+ except by further written agreement duly executed by the parties.
229+
230+ E. Binding Authority: By accepting and using the Subject Software under this Agreement, a Recipient
231+ affirms its authority to bind the Recipient to all terms and conditions of this Agreement and that
232+ Recipient hereby agrees to all terms and conditions herein.
233+
234+ F. Point of Contact: Any Recipient contact with Government Agency is to be directed to the designated
235+ representative as follows: J. Ritchie Carroll <mailto:jrcarrol@tva.gov>.
236+
237+*/
238+#endregion
239+
240+#region [ Contributor License Agreements ]
241+
242+//******************************************************************************************************
243+//
244+// Copyright © 2011, Grid Protection Alliance. All Rights Reserved.
245+//
246+// The GPA licenses this file to you under the Eclipse Public License -v 1.0 (the "License"); you may
247+// not use this file except in compliance with the License. You may obtain a copy of the License at:
248+//
249+// http://www.opensource.org/licenses/eclipse-1.0.php
250+//
251+// Unless agreed to in writing, the subject software distributed under the License is distributed on an
252+// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
253+// License for the specific language governing permissions and limitations.
254+//
255+//******************************************************************************************************
256+
257+#endregion
258+
259+using GSF.Security.Cryptography;
260+using System;
261+using System.Runtime.CompilerServices;
262+using System.Security.AccessControl;
263+using System.Security.Principal;
264+using System.Threading;
265+
266+namespace GSF.Threading
267+{
268+ /// <summary>
269+ /// Defines helper methods related to interprocess locking.
270+ /// </summary>
271+ public static class InterprocessLock
272+ {
273+ private const int MutexHash = 0;
274+ private const int SemaphoreHash = 1;
275+
276+ /// <summary>
277+ /// Gets a uniquely named interprocess <see cref="Mutex"/> associated with the specified <paramref name="name"/> that identifies a source object
278+ /// needing concurrency locking.
279+ /// </summary>
280+ /// <param name="name">Identifiying name of source object needing concurrency locking (e.g., a path and file name).</param>
281+ /// <returns>A uniquely named interprocess <see cref="Mutex"/> specific to <paramref name="name"/>; <see cref="Mutex"/> is created if it does not exist.</returns>
282+ /// <remarks>
283+ /// <para>
284+ /// This function uses a hash of the <paramref name="name"/> when creating the <see cref="Mutex"/>, not the actual <paramref name="name"/> - this way
285+ /// restrictions on the <paramref name="name"/> do not need to be a user concern. All processes needing an interprocess <see cref="Mutex"/> need to
286+ /// use this same function to ensure access to the same <see cref="Mutex"/>.
287+ /// </para>
288+ /// <para>
289+ /// The <paramref name="name"/> can be a string of any length (must not be empty, null or white space) and is not case-sensitive. All hashes of the
290+ /// <paramref name="name"/> used to create the global <see cref="Mutex"/> are first converted to lower case.
291+ /// </para>
292+ /// <para>
293+ /// The <see cref="Mutex"/> created is "Global" meaning that it will be accessible to all active application sessions including terminal service
294+ /// sessions. This is accomplished internally by prefixing the <see cref="Mutex"/> name with "Global\"; it is not necessary for the user to be
295+ /// concerned with the length or contents of the <paramref name="name"/> in this method as long as the same <paramref name="name"/> is used for
296+ /// each application. Do not use this helper function if you need to create a specifically named or non-global <see cref="Mutex"/>, such as when
297+ /// you need to interact with another application using a <see cref="Mutex"/> that does not use this function.
298+ /// </para>
299+ /// </remarks>
300+ /// <exception cref="ArgumentNullException">Argument <paramref name="name"/> cannot be empty, null or white space.</exception>
301+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
302+ public static Mutex GetNamedMutex(string name)
303+ {
304+ if (string.IsNullOrWhiteSpace(name))
305+ throw new ArgumentNullException("name", "Argument cannot be empty, null or white space.");
306+
307+ Mutex namedMutex = null;
308+ bool doesNotExist = false;
309+ bool unauthorized = false;
310+
311+ // Create a mutex name that is specific to an object (e.g., a path and file name).
312+ // Prefix mutext name with "Global\" such that mutex will apply to all active
313+ // application sessions in case terminal services is running.
314+ string mutexName = "Global\\" + Cipher.GetPasswordHash(name.ToLower(), MutexHash).Replace('\\', '-');
315+
316+ // Attempt to open the named mutex
317+ try
318+ {
319+ namedMutex = Mutex.OpenExisting(mutexName);
320+ }
321+ catch (WaitHandleCannotBeOpenedException)
322+ {
323+ doesNotExist = true;
324+ }
325+ catch (UnauthorizedAccessException)
326+ {
327+ unauthorized = true;
328+ }
329+
330+ // Mono Mutex implementations do not include ability to change access rules
331+#if MONO
332+ // If mutex does not exist we create it
333+ if (doesNotExist || unauthorized)
334+ {
335+ try
336+ {
337+ bool mutexWasCreated;
338+
339+ namedMutex = new Mutex(false, mutexName, out mutexWasCreated);
340+
341+ if (!mutexWasCreated)
342+ throw new InvalidOperationException("Failed to create mutex.");
343+ }
344+ catch (UnauthorizedAccessException ex)
345+ {
346+ throw new InvalidOperationException("Failed to create mutex: " + ex.Message);
347+ }
348+ }
349+#else
350+ // If mutex does not exist we create it
351+ if (doesNotExist)
352+ {
353+ try
354+ {
355+ MutexSecurity security = new MutexSecurity();
356+ bool mutexWasCreated;
357+
358+ security.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow));
359+ namedMutex = new Mutex(false, mutexName, out mutexWasCreated, security);
360+
361+ if (!mutexWasCreated)
362+ throw new InvalidOperationException("Failed to create mutex.");
363+ }
364+ catch (UnauthorizedAccessException)
365+ {
366+ MutexSecurity security = new MutexSecurity();
367+ bool mutexWasCreated;
368+
369+ security.AddAccessRule(new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow));
370+ namedMutex = new Mutex(false, mutexName, out mutexWasCreated, security);
371+
372+ if (!mutexWasCreated)
373+ throw new InvalidOperationException("Failed to create mutex.");
374+ }
375+ }
376+
377+ if (unauthorized)
378+ {
379+ namedMutex = Mutex.OpenExisting(mutexName, MutexRights.ReadPermissions | MutexRights.ChangePermissions);
380+
381+ // Get the current ACL. This requires MutexRights.ReadPermission
382+ MutexSecurity security = namedMutex.GetAccessControl();
383+ MutexAccessRule rule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.FullControl, AccessControlType.Allow);
384+ security.RemoveAccessRule(rule);
385+
386+ // Now grant specific user rights for less than full access
387+ rule = new MutexAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), MutexRights.Synchronize | MutexRights.Modify, AccessControlType.Allow);
388+ security.AddAccessRule(rule);
389+
390+ // Update the ACL. This requires MutexRighs.ChangePermission.
391+ namedMutex.SetAccessControl(security);
392+ namedMutex = Mutex.OpenExisting(mutexName);
393+ }
394+#endif
395+
396+ return namedMutex;
397+ }
398+
399+ /// <summary>
400+ /// Gets a uniquely named interprocess <see cref="Semaphore"/> associated with the specified <paramref name="name"/> that identifies a source object
401+ /// needing concurrency locking.
402+ /// </summary>
403+ /// <param name="name">Identifiying name of source object needing concurrency locking (e.g., a path and file name).</param>
404+ /// <param name="maximumCount">The maximum number of requests for the semaphore that can be granted concurrently.</param>
405+ /// <param name="initialCount">The initial number of requests for the semaphore that can be granted concurrently, or -1 to default to <paramref name="maximumCount"/>.</param>
406+ /// <returns>A uniquely named interprocess <see cref="Semaphore"/> specific to <paramref name="name"/>; <see cref="Semaphore"/> is created if it does not exist.</returns>
407+ /// <remarks>
408+ /// <para>
409+ /// This function uses a hash of the <paramref name="name"/> when creating the <see cref="Semaphore"/>, not the actual <paramref name="name"/> - this way
410+ /// restrictions on the <paramref name="name"/> do not need to be a user concern. All processes needing an interprocess <see cref="Semaphore"/> need to
411+ /// use this same function to ensure access to the same <see cref="Semaphore"/>.
412+ /// </para>
413+ /// <para>
414+ /// The <paramref name="name"/> can be a string of any length (must not be empty, null or white space) and is not case-sensitive. All hashes of the
415+ /// <paramref name="name"/> used to create the global <see cref="Semaphore"/> are first converted to lower case.
416+ /// </para>
417+ /// <para>
418+ /// It is not necessary for the user to be concerned with the length or contents of the <paramref name="name"/> in this method as long as the same
419+ /// <paramref name="name"/> is used for each application. Do not use this helper function if you need to create a specifically named <see cref="Semaphore"/>,
420+ /// such as when you need to interact with another application using a <see cref="Semaphore"/> that does not use this function.
421+ /// </para>
422+ /// </remarks>
423+ /// <exception cref="ArgumentNullException">Argument <paramref name="name"/> cannot be empty, null or white space.</exception>
424+ [MethodImplAttribute(MethodImplOptions.Synchronized)]
425+ public static Semaphore GetNamedSemaphore(string name, int maximumCount = 10, int initialCount = -1)
426+ {
427+ if (string.IsNullOrWhiteSpace(name))
428+ throw new ArgumentNullException("name", "Argument cannot be empty, null or white space.");
429+
430+ Semaphore namedSemaphore = null;
431+ bool doesNotExist = false;
432+ bool unauthorized = false;
433+
434+ if (initialCount < 0)
435+ initialCount = maximumCount;
436+
437+ // Create a semaphore name that is specific to an object (e.g., a path and file name).
438+ string semaphoreName = Cipher.GetPasswordHash(name.ToLower(), SemaphoreHash).Replace('\\', '-');
439+
440+ // Attempt to open the named semaphore
441+ try
442+ {
443+ namedSemaphore = Semaphore.OpenExisting(semaphoreName);
444+ }
445+ catch (WaitHandleCannotBeOpenedException)
446+ {
447+ doesNotExist = true;
448+ }
449+ catch (UnauthorizedAccessException)
450+ {
451+ unauthorized = true;
452+ }
453+
454+ // Mono Semaphore implementations do not include ability to change access rules
455+#if MONO
456+ // If semaphore does not exist we create it
457+ if (doesNotExist || unauthorized)
458+ {
459+ try
460+ {
461+ bool semaphoreWasCreated;
462+
463+ namedSemaphore = new Semaphore(initialCount, maximumCount, semaphoreName, out semaphoreWasCreated);
464+
465+ if (!semaphoreWasCreated)
466+ throw new InvalidOperationException("Failed to create semaphore.");
467+ }
468+ catch (UnauthorizedAccessException ex)
469+ {
470+ throw new InvalidOperationException("Failed to create semaphore: " + ex.Message);
471+ }
472+ }
473+#else
474+ // If semaphore does not exist we create it
475+ if (doesNotExist)
476+ {
477+ try
478+ {
479+ SemaphoreSecurity security = new SemaphoreSecurity();
480+ bool semaphoreWasCreated;
481+
482+ security.AddAccessRule(new SemaphoreAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), SemaphoreRights.FullControl, AccessControlType.Allow));
483+ namedSemaphore = new Semaphore(initialCount, maximumCount, semaphoreName, out semaphoreWasCreated, security);
484+
485+ if (!semaphoreWasCreated)
486+ throw new InvalidOperationException("Failed to create semaphore.");
487+ }
488+ catch (UnauthorizedAccessException)
489+ {
490+ SemaphoreSecurity security = new SemaphoreSecurity();
491+ bool semaphoreWasCreated;
492+
493+ security.AddAccessRule(new SemaphoreAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), SemaphoreRights.Synchronize | SemaphoreRights.Modify, AccessControlType.Allow));
494+ namedSemaphore = new Semaphore(initialCount, maximumCount, semaphoreName, out semaphoreWasCreated, security);
495+
496+ if (!semaphoreWasCreated)
497+ throw new InvalidOperationException("Failed to create semaphore.");
498+ }
499+ }
500+ else if (unauthorized)
501+ {
502+ namedSemaphore = Semaphore.OpenExisting(semaphoreName, SemaphoreRights.ReadPermissions | SemaphoreRights.ChangePermissions);
503+
504+ // Get the current ACL. This requires MutexRights.ReadPermission
505+ SemaphoreSecurity security = new SemaphoreSecurity();
506+ SemaphoreAccessRule rule = new SemaphoreAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), SemaphoreRights.FullControl, AccessControlType.Allow);
507+ security.RemoveAccessRule(rule);
508+
509+ // Now grant specific user rights for less than full access
510+ rule = new SemaphoreAccessRule(new SecurityIdentifier(WellKnownSidType.WorldSid, null), SemaphoreRights.Synchronize | SemaphoreRights.Modify, AccessControlType.Allow);
511+ security.AddAccessRule(rule);
512+
513+ // Update the ACL. This requires MutexRighs.ChangePermission.
514+ namedSemaphore.SetAccessControl(security);
515+ namedSemaphore = Semaphore.OpenExisting(semaphoreName);
516+ }
517+#endif
518+
519+ return namedSemaphore;
520+ }
521+ }
522+}

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t