summaryrefslogtreecommitdiff
path: root/evutil.c
diff options
context:
space:
mode:
authorPierce Lopez <pierce.lopez@gmail.com>2020-07-25 21:17:21 -0400
committerPierce Lopez <pierce.lopez@gmail.com>2020-07-26 18:01:35 -0400
commit65199178c6ee124a695a14983879921cb073c2df (patch)
treec029f3e89e1cbf2f4d077b9d6ed555e75421c230 /evutil.c
parent85c6759926b02094920f598d050aa72eb8dc2369 (diff)
downloadlibevent-65199178c6ee124a695a14983879921cb073c2df.tar.gz
windows socketpair tmpfile: use random prefix
fixes #1058 GetTempFileNameA() takes an optional prefix, and a "unique" long value which can optionally be zero, which causes it to automatically increment until a not-yet-existing filename is found. When libevent creates many AF_UNIX socketpairs on windows, it slows down dramatically, due to always using the same blank prefix, and GetTempFileNameA() needing to iterate through all the existing socketpair filenames. With a present and varying prefix, it will have much less need to iterate. It was also possible for a race with other processes also using blank-prefix tmpfile names to result in both trying to start using the same name at the same time (because libevent deletes the file and then re-creates it as a unix socket), which should now be much less likely. Unfortuantely, "much" is just a factor of 32k, because the prefix is only 3 characters, and windows filesystems are case-insensitive, so doing better would require more sophisticated windows API usage and charset trickyness.
Diffstat (limited to 'evutil.c')
-rw-r--r--evutil.c14
1 files changed, 12 insertions, 2 deletions
diff --git a/evutil.c b/evutil.c
index 93093b0e..a9207188 100644
--- a/evutil.c
+++ b/evutil.c
@@ -212,11 +212,21 @@ create_tmpfile(char tmpfile[MAX_PATH])
{
char short_path[MAX_PATH] = {0};
char long_path[MAX_PATH] = {0};
- char *tmp_file = tmpfile;
+ char prefix[4] = {0};
+ // GetTempFileNameA() uses up to the first three characters of the prefix
+ // and windows filesystems are case-insensitive
+ const char *base32set = "abcdefghijklmnopqrstuvwxyz012345";
+ ev_uint16_t rnd;
+
+ evutil_secure_rng_get_bytes(&rnd, sizeof(rnd));
+ prefix[0] = base32set[(rnd ) & 31];
+ prefix[1] = base32set[(rnd >> 5) & 31];
+ prefix[2] = base32set[(rnd >> 10) & 31];
+ prefix[3] = '\0';
GetTempPathA(MAX_PATH, short_path);
GetLongPathNameA(short_path, long_path, MAX_PATH);
- if (!GetTempFileNameA(long_path, NULL, 0, tmp_file)) {
+ if (!GetTempFileNameA(long_path, prefix, 0, tmpfile)) {
event_warnx("GetTempFileName failed: %d", EVUTIL_SOCKET_ERROR());
return -1;
}