aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2012-07-31 19:36:16 +0000
committerCorinna Vinschen <corinna@vinschen.de>2012-07-31 19:36:16 +0000
commit68e41cfcf4212e856ed3e75303ee11c7077d5759 (patch)
tree9607949d45c353545b096a60fe5c876236714cbb
parent217618d3d6bad5d23dca66f9517c77cd92c6404b (diff)
downloadnewlib-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/ChangeLog7
-rw-r--r--winsup/cygwin/path.cc54
-rw-r--r--winsup/cygwin/path.h1
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];