diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2012-07-31 19:36:16 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2012-07-31 19:36:16 +0000 |
commit | 68e41cfcf4212e856ed3e75303ee11c7077d5759 (patch) | |
tree | 9607949d45c353545b096a60fe5c876236714cbb | |
parent | 217618d3d6bad5d23dca66f9517c77cd92c6404b (diff) | |
download | newlib-68e41cfcf4212e856ed3e75303ee11c7077d5759.zip newlib-68e41cfcf4212e856ed3e75303ee11c7077d5759.tar.gz newlib-68e41cfcf4212e856ed3e75303ee11c7077d5759.tar.bz2 |
* path.cc (etc::dir_changed): Change `io' to a static NO_COPY
variable. Explain why. Add a muto to guard overwriting the changed_h
handle by multiple concurrent threads.
* path.h (class etc): Drop unused changed_h member.
-rw-r--r-- | winsup/cygwin/ChangeLog | 7 | ||||
-rw-r--r-- | winsup/cygwin/path.cc | 54 | ||||
-rw-r--r-- | winsup/cygwin/path.h | 1 |
3 files changed, 40 insertions, 22 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 81d0989..bf2f336 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,10 @@ +2012-07-31 Corinna Vinschen <corinna@vinschen.de> + + * path.cc (etc::dir_changed): Change `io' to a static NO_COPY + variable. Explain why. Add a muto to guard overwriting the changed_h + handle by multiple concurrent threads. + * path.h (class etc): Drop unused changed_h member. + 2012-07-30 Christopher Faylor <me.cygwin2012@cgf.cx> * winlean.h: Define constant which will be needed eventually. Remove diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index e67c91f..859e958 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -4311,46 +4311,58 @@ etc::test_file_change (int n) bool etc::dir_changed (int n) { + static muto lock NO_COPY; + static HANDLE changed_h NO_COPY; + /* io MUST be static because NtNotifyChangeDirectoryFile works asynchronously. + It may write into io after the function has left, which may result in all + sorts of stack corruption. */ + static IO_STATUS_BLOCK io NO_COPY; + if (!change_possible[n]) { - static HANDLE changed_h NO_COPY; NTSTATUS status; - IO_STATUS_BLOCK io; if (!changed_h) { OBJECT_ATTRIBUTES attr; - path_conv dir ("/etc"); - status = NtOpenFile (&changed_h, SYNCHRONIZE | FILE_LIST_DIRECTORY, - dir.get_object_attr (attr, sec_none_nih), &io, - FILE_SHARE_VALID_FLAGS, FILE_DIRECTORY_FILE); - if (!NT_SUCCESS (status)) + lock.init ("etc_dir_changed_lock")->acquire (); + if (!changed_h) { + path_conv dir ("/etc"); + status = NtOpenFile (&changed_h, + SYNCHRONIZE | FILE_LIST_DIRECTORY, + dir.get_object_attr (attr, sec_none_nih), + &io, FILE_SHARE_VALID_FLAGS, + FILE_DIRECTORY_FILE); + if (!NT_SUCCESS (status)) + { #ifdef DEBUGGING - system_printf ("NtOpenFile (%S) failed, %p", - dir.get_nt_native_path (), status); + system_printf ("NtOpenFile (%S) failed, %p", + dir.get_nt_native_path (), status); #endif - changed_h = INVALID_HANDLE_VALUE; - } - else - { - status = NtNotifyChangeDirectoryFile (changed_h, NULL, NULL, + changed_h = INVALID_HANDLE_VALUE; + } + else + { + status = NtNotifyChangeDirectoryFile (changed_h, NULL, NULL, NULL, &io, NULL, 0, FILE_NOTIFY_CHANGE_LAST_WRITE | FILE_NOTIFY_CHANGE_FILE_NAME, FALSE); - if (!NT_SUCCESS (status)) - { + if (!NT_SUCCESS (status)) + { #ifdef DEBUGGING - system_printf ("NtNotifyChangeDirectoryFile (1) failed, %p", - status); + system_printf ("NtNotifyChangeDirectoryFile (1) failed, " + "%p", status); #endif - NtClose (changed_h); - changed_h = INVALID_HANDLE_VALUE; + NtClose (changed_h); + changed_h = INVALID_HANDLE_VALUE; + } } + memset (change_possible, true, sizeof (change_possible)); } - memset (change_possible, true, sizeof (change_possible)); + lock.release (); } if (changed_h == INVALID_HANDLE_VALUE) diff --git a/winsup/cygwin/path.h b/winsup/cygwin/path.h index ba229fe..cb7480a 100644 --- a/winsup/cygwin/path.h +++ b/winsup/cygwin/path.h @@ -438,7 +438,6 @@ class etc { friend class dtable; static int curr_ix; - static HANDLE changed_h; static bool change_possible[MAX_ETC_FILES + 1]; static OBJECT_ATTRIBUTES fn[MAX_ETC_FILES + 1]; static LARGE_INTEGER last_modified[MAX_ETC_FILES + 1]; |