diff --git a/rules/S7133/csharp/metadata.json b/rules/S7133/csharp/metadata.json new file mode 100644 index 00000000000..7f560e6775b --- /dev/null +++ b/rules/S7133/csharp/metadata.json @@ -0,0 +1,23 @@ +{ + "title": "Locks should be released within the same method", + "type": "BUG", + "status": "ready", + "remediation": { + "func": "Constant\/Issue", + "constantCost": "5min" + }, + "tags": [ + ], + "defaultSeverity": "Major", + "ruleSpecification": "RSPEC-7133", + "sqKey": "S7133", + "scope": "All", + "defaultQualityProfiles": ["Sonar way"], + "quickfix": "targeted", + "code": { + "impacts": { + "RELIABILITY": "HIGH" + }, + "attribute": "CONVENTIONAL" + } +} diff --git a/rules/S7133/csharp/rule.adoc b/rules/S7133/csharp/rule.adoc new file mode 100644 index 00000000000..c95aa312906 --- /dev/null +++ b/rules/S7133/csharp/rule.adoc @@ -0,0 +1,78 @@ +This rule raises if you acquire a lock with one of the following methods, and do not release it within the same method. + +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlock.acquirereaderlock[ReaderWriterLock.AcquireReaderLock] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlock.acquirewriterlock[ReaderWriterLock.AcquireWriterLock] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim.enterreadlock[ReaderWriterLockSlim.EnterReadLock] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim.enterupgradeablereadlock[ReaderWriterLockSlim.EnterUpgradeableReadLock] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim.tryenterreadlock[ReaderWriterLockSlim.TryEnterReadLock] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim.tryenterupgradeablereadlock[ReaderWriterLockSlim.TryEnterUpgradeableReadLock] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim.enterwritelock[ReaderWriterLockSlim.EnterWriteLock] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim.tryenterwritelock[ReaderWriterLockSlim.TryEnterWriteLock] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.spinlock.enter[SpinLock.Enter] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.spinlock.tryenter[SpinLock.TryEnter] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.monitor.enter[Monitor.Enter] +* https://learn.microsoft.com/en-us/dotnet/api/system.threading.monitor.tryenter[Monitor.TryEnter] + + + +== Why is this an issue? + +Not releasing a lock in the same method where you acquire it, and releasing in another one, makes the code less clear and harder to maintain. You are also introducing the risk of not releasing a lock at all which can lead to deadlocks or exceptions. + + +=== Code examples + +==== Noncompliant code example + +[source,csharp,diff-id=1,diff-type=noncompliant] +---- +public class Example +{ + private static ReaderWriterLock rwLock = new(); + + public void AcquireWriterLock() => + rwLock.AcquireWriterLock(2000); // Noncompliant, as the lock release is on the callers responsibilty + + public void DoSomething() + { + // ... + } + + public void ReleaseWriterLock() => + rwLock.ReleaseWriterLock(); +} +---- + +==== Compliant solution + +[source,csharp,diff-id=1,diff-type=compliant] +---- +public class Example +{ + private static ReaderWriterLock rwLock = new(); + + public void DoSomething() + { + rwLock.AcquireWriterLock(2000); // Compliant, locks are released in the same method + try + { + // ... + } + finally + { + rwLock.ReleaseWriterLock(); + } + } +} +---- + +== Resources + +=== Documentation + +* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlock[ReaderWriterLock Class] +* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.threading.readerwriterlockslim[ReaderWriterLockSlim Classs] +* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.threading.spinlock[SpinLock Struct] +* Microsoft Learn - https://learn.microsoft.com/en-us/dotnet/api/system.threading.monitor[Monitor Classs] + +include::../rspecator.adoc[] \ No newline at end of file diff --git a/rules/S7133/message.adoc b/rules/S7133/message.adoc new file mode 100644 index 00000000000..1433517ee78 --- /dev/null +++ b/rules/S7133/message.adoc @@ -0,0 +1,4 @@ +=== Message + +You should release this lock in the same method. + diff --git a/rules/S7133/metadata.json b/rules/S7133/metadata.json new file mode 100644 index 00000000000..2c63c085104 --- /dev/null +++ b/rules/S7133/metadata.json @@ -0,0 +1,2 @@ +{ +} diff --git a/rules/S7133/rspecator.adoc b/rules/S7133/rspecator.adoc new file mode 100644 index 00000000000..a791a6b354e --- /dev/null +++ b/rules/S7133/rspecator.adoc @@ -0,0 +1,9 @@ +ifdef::env-github,rspecator-view[] + +''' +== Implementation Specification +(visible only on this page) + +include::message.adoc[] + +endif::env-github,rspecator-view[]