diff options
author | Pierce Lopez <pierce.lopez@gmail.com> | 2020-07-25 21:17:21 -0400 |
---|---|---|
committer | Pierce Lopez <pierce.lopez@gmail.com> | 2020-07-26 18:01:35 -0400 |
commit | 65199178c6ee124a695a14983879921cb073c2df (patch) | |
tree | c029f3e89e1cbf2f4d077b9d6ed555e75421c230 /evutil.c | |
parent | 85c6759926b02094920f598d050aa72eb8dc2369 (diff) | |
download | libevent-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.c | 14 |
1 files changed, 12 insertions, 2 deletions
@@ -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; } |