/// <summary>Start monitoring the current directory.</summary> private void StartRaisingEvents() { // If we're already running, don't do anything. if (!IsHandleInvalid(_directoryHandle)) { return; } // Create handle to directory being monitored var defaultSecAttrs = default(Interop.mincore.SECURITY_ATTRIBUTES); _directoryHandle = Interop.mincore.CreateFile( lpFileName: _directory, dwDesiredAccess: Interop.mincore.FileOperations.FILE_LIST_DIRECTORY, dwShareMode: FileShare.Read | FileShare.Delete | FileShare.Write, securityAttrs: ref defaultSecAttrs, dwCreationDisposition: FileMode.Open, dwFlagsAndAttributes: Interop.mincore.FileOperations.FILE_FLAG_BACKUP_SEMANTICS | Interop.mincore.FileOperations.FILE_FLAG_OVERLAPPED, hTemplateFile: IntPtr.Zero); if (IsHandleInvalid(_directoryHandle)) { _directoryHandle = null; throw new FileNotFoundException(SR.Format(SR.FSW_IOError, _directory)); } // Create the state associated with the operation of monitoring the direction AsyncReadState state; try { // Start ignoring all events that were initiated before this, and // allocate the buffer to be pinned and used for the duration of the operation int session = Interlocked.Increment(ref _currentSession); byte[] buffer = AllocateBuffer(); // Store all state, including a preallocated overlapped, into the state object that'll be // passed from iteration to iteration during the lifetime of the operation. The buffer will be pinned // from now until the end of the operation. state = new AsyncReadState(session, buffer, _directoryHandle, ThreadPoolBoundHandle.BindHandle(_directoryHandle)); unsafe { state.PreAllocatedOverlapped = new PreAllocatedOverlapped(ReadDirectoryChangesCallback, state, buffer); } } catch { // Make sure we don't leave a valid directory handle set if we're not running _directoryHandle.Dispose(); _directoryHandle = null; throw; } // Start monitoring _enabled = true; Monitor(state); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public void BindHandle_ClosedSyncHandleAsHandle_ThrowsArgumentException() { using (Win32Handle handle = HandleFactory.CreateSyncFileHandleForWrite(GetTestFilePath())) { handle.CloseWithoutDisposing(); AssertExtensions.Throws <ArgumentException>("handle", () => { ThreadPoolBoundHandle.BindHandle(handle); }); } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void FlowsAsyncLocalsToCallback_PreAllocatedOverlapped(bool shouldFlow) { // Makes sure that we flow async locals to callback const int DATA_SIZE = 2; SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"AsyncLocal.tmp")); ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle); OverlappedContext context = new OverlappedContext(); byte[] data = new byte[DATA_SIZE]; AsyncLocal <int> asyncLocal = new AsyncLocal <int>(); asyncLocal.Value = 10; int?result = null; IOCompletionCallback callback = (_, __, ___) => { result = asyncLocal.Value; OnOverlappedOperationCompleted(_, __, ___); }; using (PreAllocatedOverlapped preAlloc = shouldFlow ? new PreAllocatedOverlapped(callback, context, data) : PreAllocatedOverlapped.UnsafeCreate(callback, context, data)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped(preAlloc); fixed(byte *p = data) { int retval = DllImport.WriteFile(boundHandle.Handle, p, DATA_SIZE, IntPtr.Zero, overlapped); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastPInvokeError()); } // Wait for overlapped operation to complete context.Event.WaitOne(); } boundHandle.FreeNativeOverlapped(overlapped); } boundHandle.Dispose(); handle.Dispose(); Assert.Equal( shouldFlow ? 10 : 0, result); }
private ThreadPoolBoundHandle CreateThreadPoolBoundHandle(SafeHandle handle, [CallerMemberName] string memberName = null, [CallerLineNumber] int lineNumber = 0) { if (handle == null) { handle = HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath(null, memberName, lineNumber)); // ThreadPoolBoundHandle does not take ownership of the handle; // we must close it _handlesToDispose.Add(handle); } return(ThreadPoolBoundHandle.BindHandle(handle)); }
private ThreadPoolBoundHandle CreateThreadPoolBoundHandle(SafeHandle handle, [CallerMemberName] string memberName = null, [CallerLineNumber] int lineNumber = 0) { handle = handle ?? HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath(null, memberName, lineNumber)); try { return(ThreadPoolBoundHandle.BindHandle(handle)); } catch (ArgumentException ex) when(ex.GetType() == typeof(ArgumentException)) { // TODO: Remove this try/catch, which is intended to help with debugging https://github.com/dotnet/corefx/issues/18058 throw new ArgumentException("Handle value: " + handle.DangerousGetHandle(), ex.ParamName, ex); } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public void BindHandle_AlreadyBoundHandleAsHandle_ThrowsArgumentException() { using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite()) { // Once ThreadPoolBoundHandle.BindHandle(handle); AssertExtensions.Throws <ArgumentException>("handle", () => { // Twice ThreadPoolBoundHandle.BindHandle(handle); }); } }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsNull_ReturnsNull() { using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath())) { using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, (object)null, new byte[0]); object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped); Assert.Null(result); boundHandle.FreeNativeOverlapped(overlapped); } } }
// Win32 file channel impl // TODO: Other platforms public unsafe void OpenReadFile(string path) { var fileHandle = CreateFile(path, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, EFileAttributes.Overlapped, IntPtr.Zero); var handle = ThreadPoolBoundHandle.BindHandle(fileHandle); var readOperation = new ReadOperation { Channel = _channel, FileHandle = fileHandle, Handle = handle, IOCallback = IOCallback }; _channel.OnStartReading(readOperation.Read); _channel.OnDispose(fileHandle.Dispose); }
internal RequestQueue(UrlGroup urlGroup) { _urlGroup = urlGroup; var queueName = "IISConsole"; HttpRequestQueueV2Handle requestQueueHandle = null; var statusCode = HttpApi.HttpCreateRequestQueue( HttpApi.Version, queueName, null, HttpApiTypes.HTTP_CREATE_REQUEST_QUEUE_FLAGS.HTTP_CREATE_REQUEST_QUEUE_FLAG_CONTROLLER, out requestQueueHandle); if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { throw new HttpSysException((int)statusCode); } Handle = requestQueueHandle; BoundHandle = ThreadPoolBoundHandle.BindHandle(Handle); }
public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsObject_ReturnsObject() { object context = new object(); using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite()) { using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, context, new byte[0]); object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped); Assert.Same(context, result); boundHandle.FreeNativeOverlapped(overlapped); } } }
// Binds the Socket Win32 Handle to the ThreadPool's CompletionPort. public ThreadPoolBoundHandle GetOrAllocateThreadPoolBoundHandle() { if (_released) { // Keep the exception message pointing at the external type. throw new ObjectDisposedException(typeof(Socket).FullName); } // Check to see if the socket native _handle is already // bound to the ThreadPool's completion port. if (_iocpBoundHandle == null) { lock (_iocpBindingLock) { if (_iocpBoundHandle == null) { // Bind the socket native _handle to the ThreadPool. if (GlobalLog.IsEnabled) { GlobalLog.Print("SafeCloseSocket#" + LoggingHash.HashString(this) + "::BindToCompletionPort() calling ThreadPool.BindHandle()"); } try { // The handle (this) may have been already released: // E.g.: The socket has been disposed in the main thread. A completion callback may // attempt starting another operation. _iocpBoundHandle = ThreadPoolBoundHandle.BindHandle(this); } catch (Exception exception) { if (ExceptionCheck.IsFatal(exception)) { throw; } CloseAsIs(); throw; } } } } return(_iocpBoundHandle); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void GetNativeOverlappedState_WhenUnderlyingStateIsIAsyncResult_ReturnsIAsyncResult() { // CoreCLR/Desktop CLR version of overlapped sits on top of Overlapped class // and treats IAsyncResult specially, which is why we special case this case. AsyncResult context = new AsyncResult(); using (SafeHandle handle = HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath())) { using (ThreadPoolBoundHandle boundHandle = ThreadPoolBoundHandle.BindHandle(handle)) { NativeOverlapped *overlapped = boundHandle.AllocateNativeOverlapped((_, __, ___) => { }, context, new byte[0]); object result = ThreadPoolBoundHandle.GetNativeOverlappedState(overlapped); Assert.Same(context, result); boundHandle.FreeNativeOverlapped(overlapped); } } }
private void StartRaisingEvents() { // If we're attached, don't do anything. if (!IsHandleInvalid) { return; } // Create handle to directory being monitored _directoryHandle = NativeMethods.CreateFile(_directory, // Directory name UnsafeNativeMethods.FILE_LIST_DIRECTORY, // access (read-write) mode UnsafeNativeMethods.FILE_SHARE_READ | UnsafeNativeMethods.FILE_SHARE_DELETE | UnsafeNativeMethods.FILE_SHARE_WRITE, // share mode null, // security descriptor UnsafeNativeMethods.OPEN_EXISTING, // how to create UnsafeNativeMethods.FILE_FLAG_BACKUP_SEMANTICS | UnsafeNativeMethods.FILE_FLAG_OVERLAPPED, // file attributes new SafeFileHandle(IntPtr.Zero, false) // file with attributes to copy ); if (IsHandleInvalid) { throw new FileNotFoundException(SR.Format(SR.FSW_IOError, _directory)); } _stopListening = false; // Start ignoring all events that were initiated before this. Interlocked.Increment(ref _currentSession); // Attach handle to thread pool _threadPoolBinding = ThreadPoolBoundHandle.BindHandle(_directoryHandle); _enabled = true; // Setup IO completion port Monitor(null); }
// Win32 file impl // TODO: Other platforms public unsafe void OpenReadFile(string path) { var fileHandle = CreateFile(path, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, EFileAttributes.Overlapped, IntPtr.Zero); var handle = ThreadPoolBoundHandle.BindHandle(fileHandle); var readOperation = new ReadOperation { Writer = _writer, FileHandle = fileHandle, ThreadPoolBoundHandle = handle, IOCallback = IOCallback }; var overlapped = new PreAllocatedOverlapped(IOCallback, readOperation, null); readOperation.PreAllocatedOverlapped = overlapped; Task.Factory.StartNew(state => { ((ReadOperation)state).Read(); }, readOperation); }
// Win32 file channel impl // TODO: Other platforms public unsafe void OpenReadFile(string path) { var fileHandle = CreateFile(path, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, EFileAttributes.Overlapped, IntPtr.Zero); var handle = ThreadPoolBoundHandle.BindHandle(fileHandle); var readOperation = new ReadOperation { Channel = _channel, FileHandle = fileHandle, ThreadPoolBoundHandle = handle, IOCallback = IOCallback }; var overlapped = new PreAllocatedOverlapped(IOCallback, readOperation, null); readOperation.PreAllocatedOverlapped = overlapped; _channel.ReadingStarted.ContinueWith((t, state) => { ((ReadOperation)state).Read(); }, readOperation); }
private static ThreadPoolBoundHandle CreateThreadPoolBoundHandle(SafeHandle handle) { handle = handle ?? HandleFactory.CreateAsyncFileHandleForWrite(); return(ThreadPoolBoundHandle.BindHandle(handle)); }
/// <summary>Initializes the handle to be used asynchronously.</summary> /// <param name="handle">The handle.</param> private void InitializeAsyncHandle(SafePipeHandle handle) { // If the handle is of async type, bind the handle to the ThreadPool so that we can use // the async operations (it's needed so that our native callbacks get called). _threadPoolBinding = ThreadPoolBoundHandle.BindHandle(handle); }
private ThreadPoolBoundHandle CreateThreadPoolBoundHandle(SafeHandle handle, [CallerMemberName] string memberName = null, [CallerLineNumber] int lineNumber = 0) { handle = handle ?? HandleFactory.CreateAsyncFileHandleForWrite(GetTestFilePath(null, memberName, lineNumber)); return(ThreadPoolBoundHandle.BindHandle(handle)); }
[PlatformSpecific(TestPlatforms.Windows)] // ThreadPoolBoundHandle.BindHandle is not supported on Unix public unsafe void MultipleOperationsOverMultipleHandles() { const int DATA_SIZE = 2; SafeHandle handle1 = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"MultipleOperationsOverMultipleHandle1.tmp")); SafeHandle handle2 = HandleFactory.CreateAsyncFileHandleForWrite(Path.Combine(TestDirectory, @"MultipleOperationsOverMultipleHandle2.tmp")); ThreadPoolBoundHandle boundHandle1 = ThreadPoolBoundHandle.BindHandle(handle1); ThreadPoolBoundHandle boundHandle2 = ThreadPoolBoundHandle.BindHandle(handle2); OverlappedContext result1 = new OverlappedContext(); OverlappedContext result2 = new OverlappedContext(); byte[] data1 = new byte[DATA_SIZE]; data1[0] = (byte)'A'; data1[1] = (byte)'B'; byte[] data2 = new byte[DATA_SIZE]; data2[0] = (byte)'C'; data2[1] = (byte)'D'; PreAllocatedOverlapped preAlloc1 = new PreAllocatedOverlapped(OnOverlappedOperationCompleted, result1, data1); PreAllocatedOverlapped preAlloc2 = new PreAllocatedOverlapped(OnOverlappedOperationCompleted, result2, data2); for (int i = 0; i < 10; i++) { NativeOverlapped *overlapped1 = boundHandle1.AllocateNativeOverlapped(preAlloc1); NativeOverlapped *overlapped2 = boundHandle2.AllocateNativeOverlapped(preAlloc2); fixed(byte *p1 = data1, p2 = data2) { int retval = DllImport.WriteFile(boundHandle1.Handle, p1, DATA_SIZE, IntPtr.Zero, overlapped1); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } retval = DllImport.WriteFile(boundHandle2.Handle, p2, DATA_SIZE, IntPtr.Zero, overlapped2); if (retval == 0) { Assert.Equal(DllImport.ERROR_IO_PENDING, Marshal.GetLastWin32Error()); } // Wait for overlapped operations to complete WaitHandle.WaitAll(new WaitHandle[] { result1.Event, result2.Event }); } boundHandle1.FreeNativeOverlapped(overlapped1); boundHandle2.FreeNativeOverlapped(overlapped2); result1.Event.Reset(); result2.Event.Reset(); Assert.Equal(0, result1.ErrorCode); Assert.Equal(0, result2.ErrorCode); Assert.Equal(DATA_SIZE, result1.BytesWritten); Assert.Equal(DATA_SIZE, result2.BytesWritten); } boundHandle1.Dispose(); boundHandle2.Dispose(); preAlloc1.Dispose(); preAlloc2.Dispose(); handle1.Dispose(); handle2.Dispose(); }
private RequestQueue(UrlGroup?urlGroup, string?requestQueueName, RequestQueueMode mode, ILogger logger, bool receiver) { _mode = mode; UrlGroup = urlGroup; _logger = logger; var flags = HttpApiTypes.HTTP_CREATE_REQUEST_QUEUE_FLAG.None; Created = true; if (_mode == RequestQueueMode.Attach) { flags = HttpApiTypes.HTTP_CREATE_REQUEST_QUEUE_FLAG.OpenExisting; Created = false; if (receiver) { flags |= HttpApiTypes.HTTP_CREATE_REQUEST_QUEUE_FLAG.Delegation; } } var statusCode = HttpApi.HttpCreateRequestQueue( HttpApi.Version, requestQueueName, null, flags, out var requestQueueHandle); if (_mode == RequestQueueMode.CreateOrAttach && statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_ALREADY_EXISTS) { // Tried to create, but it already exists so attach to it instead. Created = false; flags = HttpApiTypes.HTTP_CREATE_REQUEST_QUEUE_FLAG.OpenExisting; statusCode = HttpApi.HttpCreateRequestQueue( HttpApi.Version, requestQueueName, null, flags, out requestQueueHandle); } if (flags.HasFlag(HttpApiTypes.HTTP_CREATE_REQUEST_QUEUE_FLAG.OpenExisting) && statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_FILE_NOT_FOUND) { throw new HttpSysException((int)statusCode, $"Failed to attach to the given request queue '{requestQueueName}', the queue could not be found."); } else if (statusCode == UnsafeNclNativeMethods.ErrorCodes.ERROR_INVALID_NAME) { throw new HttpSysException((int)statusCode, $"The given request queue name '{requestQueueName}' is invalid."); } else if (statusCode != UnsafeNclNativeMethods.ErrorCodes.ERROR_SUCCESS) { throw new HttpSysException((int)statusCode); } // Disabling callbacks when IO operation completes synchronously (returns ErrorCodes.ERROR_SUCCESS) if (HttpSysListener.SkipIOCPCallbackOnSuccess && !UnsafeNclNativeMethods.SetFileCompletionNotificationModes( requestQueueHandle, UnsafeNclNativeMethods.FileCompletionNotificationModes.SkipCompletionPortOnSuccess | UnsafeNclNativeMethods.FileCompletionNotificationModes.SkipSetEventOnHandle)) { requestQueueHandle.Dispose(); throw new HttpSysException(Marshal.GetLastWin32Error()); } Handle = requestQueueHandle; BoundHandle = ThreadPoolBoundHandle.BindHandle(Handle); if (!Created) { Log.AttachedToQueue(_logger, requestQueueName); } }
public void BindHandle_ValidHandle_ThrowsPlatformNotSupportedException() { Assert.Throws <PlatformNotSupportedException>(() => ThreadPoolBoundHandle.BindHandle(new Win32Handle(new IntPtr(1)))); }
/// <summary>Start monitoring the current directory.</summary> private void StartRaisingEvents() { // If we're called when "Initializing" is true, set enabled to true if (IsSuspended()) { _enabled = true; return; } // If we're already running, don't do anything. if (!IsHandleInvalid(_directoryHandle)) { return; } // Create handle to directory being monitored _directoryHandle = Interop.Kernel32.CreateFile( lpFileName: _directory, dwDesiredAccess: Interop.Kernel32.FileOperations.FILE_LIST_DIRECTORY, dwShareMode: FileShare.Read | FileShare.Delete | FileShare.Write, dwCreationDisposition: FileMode.Open, dwFlagsAndAttributes: Interop.Kernel32.FileOperations.FILE_FLAG_BACKUP_SEMANTICS | Interop.Kernel32.FileOperations.FILE_FLAG_OVERLAPPED); if (IsHandleInvalid(_directoryHandle)) { _directoryHandle = null; throw new FileNotFoundException(SR.Format(SR.FSW_IOError, _directory)); } // Create the state associated with the operation of monitoring the direction AsyncReadState state; try { // Start ignoring all events that were initiated before this, and // allocate the buffer to be pinned and used for the duration of the operation int session = Interlocked.Increment(ref _currentSession); byte[] buffer = AllocateBuffer(); // Store all state, including a preallocated overlapped, into the state object that'll be // passed from iteration to iteration during the lifetime of the operation. The buffer will be pinned // from now until the end of the operation. state = new AsyncReadState(session, buffer, _directoryHandle, ThreadPoolBoundHandle.BindHandle(_directoryHandle), this); unsafe { state.PreAllocatedOverlapped = new PreAllocatedOverlapped((errorCode, numBytes, overlappedPointer) => { AsyncReadState state = (AsyncReadState)ThreadPoolBoundHandle.GetNativeOverlappedState(overlappedPointer) !; state.ThreadPoolBinding.FreeNativeOverlapped(overlappedPointer); if (state.WeakWatcher.TryGetTarget(out FileSystemWatcher? watcher)) { watcher.ReadDirectoryChangesCallback(errorCode, numBytes, state); } }, state, buffer); } } catch { // Make sure we don't leave a valid directory handle set if we're not running _directoryHandle.Dispose(); _directoryHandle = null; throw; } // Start monitoring _enabled = true; Monitor(state); }