| 848 | } |
| 849 | |
| 850 | static bool windows_private_file_prepare(const char *directory, const char *base) { |
| 851 | /* cbm_daemon_ipc_private_log_open supplies the same explicit protected |
| 852 | * current-SID DACL and reparse/owner checks as the daemon's operation log. |
| 853 | * Its brief FILE_SHARE_READ handle can collide with a concurrent opener, |
| 854 | * so retry that transient window rather than dropping a conflict event. |
| 855 | * The retry budget is a short deadline, not a count: Sleep(2) rounds up |
| 856 | * to the ~16 ms timer granularity, and a permanently obstructed path |
| 857 | * (e.g. a directory squatting on it) must fail fast — a rejected client |
| 858 | * is waiting behind this on the hello path with its own timeout. */ |
| 859 | ULONGLONG obstruction_deadline = GetTickCount64() + 250; |
| 860 | /* Genuine share collisions get a wider budget than obstruction: with |
| 861 | * many concurrent appenders on a loaded, sanitized CI runner the |
| 862 | * last-in-line writer can legitimately spend more than 250 ms behind |
| 863 | * its peers' brief exclusive windows, and the no-drop contract for |
| 864 | * conflict events outranks latency there — while a permanently |
| 865 | * obstructed path (a directory squatting on the name) still fails |
| 866 | * inside 250 ms, because a rejected client is waiting behind this on |
| 867 | * the hello path with its own timeout. */ |
| 868 | ULONGLONG contention_deadline = GetTickCount64() + 2000; |
| 869 | for (;;) { |
| 870 | SetLastError(ERROR_SUCCESS); |
| 871 | FILE *file = cbm_daemon_ipc_private_log_open(directory, base, SIZE_MAX); |
| 872 | if (file) { |
| 873 | return fclose(file) == 0; |
| 874 | } |
| 875 | DWORD open_error = GetLastError(); |
| 876 | bool transient_collision = |
| 877 | open_error == ERROR_SHARING_VIOLATION || open_error == ERROR_LOCK_VIOLATION; |
| 878 | ULONGLONG deadline = transient_collision ? contention_deadline : obstruction_deadline; |
| 879 | if (GetTickCount64() >= deadline) { |
| 880 | return false; |
| 881 | } |
| 882 | Sleep(2); |
| 883 | } |
| 884 | } |
| 885 | |
| 886 | static HANDLE windows_lock_open(const wchar_t *path) { |
| 887 | for (unsigned int attempt = 0; attempt < 100; attempt++) { |
no test coverage detected