And*_*tel 8 c# acl file-permissions distributed-computing
我有一个应用程序在多个服务器上运行应用一些ACL.
问题是当多个服务器应用于相同的文件夹结构(即三个级别)时,通常只有一级和三级应用了ACL,但是没有例外.
我用并行任务创建了一个测试(模拟不同的服务器):
[TestMethod]
public void ApplyACL()
{
var baseDir = Path.Combine(Path.GetTempPath(), "ACL-PROBLEM");
if (Directory.Exists(baseDir))
{
Directory.Delete(baseDir, true);
}
var paths = new[]
{
Path.Combine(baseDir, "LEVEL-1"),
Path.Combine(baseDir, "LEVEL-1", "LEVEL-2"),
Path.Combine(baseDir, "LEVEL-1", "LEVEL-2", "LEVEL-3")
};
//create folders and files, so the ACL takes some time to apply
foreach (var dir in paths)
{
Directory.CreateDirectory(dir);
for (int i = 0; i < 1000; i++)
{
var id = string.Format("{0:000}", i);
File.WriteAllText(Path.Combine(dir, id + ".txt"), id);
}
}
var sids = new[]
{
"S-1-5-21-448539723-725345543-1417001333-1111111",
"S-1-5-21-448539723-725345543-1417001333-2222222",
"S-1-5-21-448539723-725345543-1417001333-3333333"
};
var taskList = new List<Task>();
for (int i = 0; i < paths.Length; i++)
{
taskList.Add(CreateTask(i + 1, paths[i], sids[i]));
}
Parallel.ForEach(taskList, t => t.Start());
Task.WaitAll(taskList.ToArray());
var output = new StringBuilder();
var failed = false;
for (int i = 0; i < paths.Length; i++)
{
var ok = Directory.GetAccessControl(paths[i])
.GetAccessRules(true, false, typeof(SecurityIdentifier))
.OfType<FileSystemAccessRule>()
.Any(f => f.IdentityReference.Value == sids[i]);
if (!ok)
{
failed = true;
}
output.AppendLine(paths[i].Remove(0, baseDir.Length + 1) + " --> " + (ok ? "OK" : "ERROR"));
}
Debug.WriteLine(output);
if (failed)
{
Assert.Fail();
}
}
private static Task CreateTask(int i, string path, string sid)
{
return new Task(() =>
{
var start = DateTime.Now;
Debug.WriteLine("Task {0} start: {1:HH:mm:ss.fffffff}", i, start);
var fileSystemAccessRule = new FileSystemAccessRule(new SecurityIdentifier(sid),
FileSystemRights.Modify | FileSystemRights.Synchronize,
InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit,
PropagationFlags.None,
AccessControlType.Allow);
var directorySecurity = Directory.GetAccessControl(path);
directorySecurity.ResetAccessRule(fileSystemAccessRule);
Directory.SetAccessControl(path, directorySecurity);
Debug.WriteLine("Task {0} finish: {1:HH:mm:ss.fffffff} ({2} ms)", i, DateTime.Now, (DateTime.Now - start).TotalMilliseconds);
});
}
Run Code Online (Sandbox Code Playgroud)
我遇到了同样的问题:通常(但并非总是)只有第一级和第三级应用了ACL.
为什么这样,我该如何解决这个问题?
这是一个有趣的谜题。
我已经启动了您的测试,几乎每次运行都会重现问题。而且 ACL 通常也不适用于 LEVEL-3。
但是,如果任务不并行运行,则该问题不会重现。此外,如果目录不包含这 1000 个文件,则问题重现的频率就会大大降低。
这种行为与经典的竞争条件非常相似。
我没有找到有关此主题的任何明确信息,但似乎在重叠目录树上应用 ACL 不是线程安全操作。
为了确认这一点,我们需要分析SetAccessControl()(或者更确切地说是底层 Windows API 调用)的实现。但让我们试着想象一下它可能是什么。
SetAccessControl()DirectorySecurity为给定的目录和记录调用。SetAccessControl()父目录的调用也执行相同的操作。最后它将覆盖在步骤 4 中创建的记录。当然,所描述的流程只是一个假设。我们需要 NTFS 或 Windows 内部专家来确认这一点。
但观察到的行为几乎肯定表明了竞争状况。只要避免在重叠的目录树上并行应用 ACL 就可以睡个好觉了。
| 归档时间: |
|
| 查看次数: |
389 次 |
| 最近记录: |