Skip to content

Commit 441488f

Browse files
Support thread and process concurrency (#135)
1 parent 74a05f1 commit 441488f

File tree

3 files changed

+120
-22
lines changed

3 files changed

+120
-22
lines changed

WebDriverManager/DriverManager.cs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System;
12
using System.Net;
23
using WebDriverManager.DriverConfigs;
34
using WebDriverManager.Helpers;
@@ -31,12 +32,21 @@ public DriverManager WithProxy(IWebProxy proxy)
3132
return this;
3233
}
3334

35+
[Obsolete("binaryName parameter is redundant, use SetUpDriver(url, binaryPath)")]
3436
public string SetUpDriver(string url, string binaryPath, string binaryName)
3537
{
36-
var zipPath = FileHelper.GetZipDestination(url);
37-
binaryPath = _binaryService.SetupBinary(url, zipPath, binaryPath, binaryName);
38-
_variableService.SetupVariable(binaryPath);
39-
return binaryPath;
38+
lock (Object)
39+
{
40+
return SetUpDriverImpl(url, binaryPath);
41+
}
42+
}
43+
44+
public string SetUpDriver(string url, string binaryPath)
45+
{
46+
lock (Object)
47+
{
48+
return SetUpDriverImpl(url, binaryPath);
49+
}
4050
}
4151

4252
public string SetUpDriver(IDriverConfig config, string version = VersionResolveStrategy.Latest,
@@ -52,10 +62,18 @@ public string SetUpDriver(IDriverConfig config, string version = VersionResolveS
5262
url = UrlHelper.BuildUrl(url, version);
5363
var binaryPath = FileHelper.GetBinDestination(config.GetName(), version, architecture,
5464
config.GetBinaryName());
55-
return SetUpDriver(url, binaryPath, config.GetBinaryName());
65+
return SetUpDriverImpl(url, binaryPath);
5666
}
5767
}
5868

69+
private string SetUpDriverImpl(string url, string binaryPath)
70+
{
71+
var zipPath = FileHelper.GetZipDestination(url);
72+
binaryPath = _binaryService.SetupBinary(url, zipPath, binaryPath);
73+
_variableService.SetupVariable(binaryPath);
74+
return binaryPath;
75+
}
76+
5977
private static string GetVersionToDownload(IDriverConfig config, string version)
6078
{
6179
switch (version)
Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
namespace WebDriverManager.Services
1+
using System;
2+
3+
namespace WebDriverManager.Services
24
{
35
public interface IBinaryService
46
{
7+
[Obsolete("binaryName parameter is redundant, use SetupBinary(url, zipDestination, binDestination)")]
58
string SetupBinary(string url, string zipDestination, string binDestination, string binaryName);
9+
10+
string SetupBinary(string url, string zipDestination, string binDestination);
611
}
712
}

WebDriverManager/Services/Impl/BinaryService.cs

Lines changed: 91 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -7,45 +7,120 @@
77
using System.Net;
88
using System.Runtime.InteropServices;
99
using System.Text;
10-
using WebDriverManager.Helpers;
1110

1211
namespace WebDriverManager.Services.Impl
1312
{
1413
public class BinaryService : IBinaryService
1514
{
1615
public IWebProxy Proxy { get; set; }
1716

17+
[Obsolete("binaryName parameter is redundant, use SetupBinary(url, zipDestination, binDestination)")]
1818
public string SetupBinary(string url, string zipDestination, string binDestination, string binaryName)
1919
{
20-
if (File.Exists(binDestination)) return binDestination;
21-
FileHelper.CreateDestinationDirectory(zipDestination);
22-
zipDestination = DownloadZip(url, zipDestination);
23-
FileHelper.CreateDestinationDirectory(binDestination);
20+
return SetupBinary(url, zipDestination, binDestination);
21+
}
22+
23+
public string SetupBinary(string url, string zipPath, string binaryPath)
24+
{
25+
var zipDir = Path.GetDirectoryName(zipPath);
26+
var binaryDir = Path.GetDirectoryName(binaryPath);
27+
var binaryName = Path.GetFileName(binaryPath);
28+
29+
//
30+
// If the destination already exists, we don't have to do anything
31+
//
32+
if (Directory.Exists(binaryDir)) return binaryPath;
33+
34+
//
35+
// Download the driver
36+
//
37+
Directory.CreateDirectory(zipDir);
38+
zipPath = DownloadZip(url, zipPath);
39+
40+
//
41+
// Copy or extract binary(s) into a staging directory
42+
//
43+
var stagingDir = Path.Combine(zipDir, "staging");
44+
var stagingPath = Path.Combine(stagingDir, binaryName);
45+
46+
Directory.CreateDirectory(stagingDir);
2447

25-
if (zipDestination.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
48+
if (zipPath.EndsWith(".exe", StringComparison.OrdinalIgnoreCase))
2649
{
27-
File.Copy(zipDestination, binDestination);
50+
File.Copy(zipPath, stagingPath);
2851
}
29-
else if (zipDestination.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
52+
else if (zipPath.EndsWith(".zip", StringComparison.OrdinalIgnoreCase))
3053
{
31-
UnZip(zipDestination, binDestination, binaryName);
54+
UnZip(zipPath, stagingPath, binaryName);
3255
}
33-
else if (zipDestination.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase))
56+
else if (zipPath.EndsWith(".tar.gz", StringComparison.OrdinalIgnoreCase))
3457
{
35-
UnZipTgz(zipDestination, binDestination);
58+
UnZipTgz(zipPath, stagingPath);
3659
}
3760

3861
#if NETSTANDARD
39-
if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
40-
RuntimeInformation.IsOSPlatform(OSPlatform.OSX))
62+
var needsChmod =
63+
RuntimeInformation.IsOSPlatform(OSPlatform.Linux) ||
64+
RuntimeInformation.IsOSPlatform(OSPlatform.OSX);
65+
66+
if (needsChmod)
4167
{
42-
var chmod = Process.Start("chmod", $"+x {binDestination}");
68+
var chmod = Process.Start("chmod", $"+x {stagingPath}");
4369
chmod?.WaitForExit();
4470
}
4571
#endif
4672

47-
RemoveZip(zipDestination);
48-
return binDestination;
73+
//
74+
// Create the destination parent directory if it doesn't exist
75+
//
76+
var binaryParentDir = Path.GetDirectoryName(binaryDir);
77+
Directory.CreateDirectory(binaryParentDir);
78+
79+
//
80+
// Atomically rename the staging directory to the destination directory
81+
//
82+
// If a parallel thread or process races us and wins, the destination will already exist and this will fail
83+
// with an IOException.
84+
//
85+
Exception renameException = null;
86+
try
87+
{
88+
Directory.Move(stagingDir, binaryDir);
89+
}
90+
catch (Exception ex)
91+
{
92+
renameException = ex;
93+
}
94+
95+
//
96+
// Regardless of what happens, do a best-effort clean up
97+
//
98+
try
99+
{
100+
if (Directory.Exists(stagingDir)) Directory.Delete(stagingDir, true);
101+
}
102+
catch (Exception ex)
103+
{
104+
Console.Error.WriteLine(ex.ToString());
105+
}
106+
try
107+
{
108+
RemoveZip(zipPath);
109+
}
110+
catch (Exception ex)
111+
{
112+
Console.Error.WriteLine(ex.ToString());
113+
}
114+
115+
//
116+
// If the destination still doesn't exist, it means the rename failed in an unexpected way
117+
//
118+
if (!Directory.Exists(binaryDir))
119+
{
120+
throw new Exception($"Error writing {binaryDir}", renameException);
121+
}
122+
123+
return binaryPath;
49124
}
50125

51126
public string DownloadZip(string url, string destination)

0 commit comments

Comments
 (0)