mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 06:43:32 +00:00
Bug 1910513 - Update tokio to 1.39.2. r=nika,supply-chain-reviewers
This also update mio to 1.0.1 and tokio-macros to 2.4.0 Differential Revision: https://phabricator.services.mozilla.com/D218157
This commit is contained in:
parent
130bcf8632
commit
7c72645ded
@ -30,11 +30,6 @@ git = "https://github.com/gfx-rs/wgpu"
|
||||
rev = "aeb2067e8120c1ff480625c00b9571db8d01d5a4"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/glandium/mio?rev=9a2ef335c366044ffe73b1c4acabe50a1daefe05"]
|
||||
git = "https://github.com/glandium/mio"
|
||||
rev = "9a2ef335c366044ffe73b1c4acabe50a1daefe05"
|
||||
replace-with = "vendored-sources"
|
||||
|
||||
[source."git+https://github.com/hsivonen/any_all_workaround?rev=7fb1b7034c9f172aade21ee1c8554e8d8a48af80"]
|
||||
git = "https://github.com/hsivonen/any_all_workaround"
|
||||
rev = "7fb1b7034c9f172aade21ee1c8554e8d8a48af80"
|
||||
|
64
Cargo.lock
generated
64
Cargo.lock
generated
@ -263,7 +263,7 @@ dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"mach",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -285,13 +285,13 @@ dependencies = [
|
||||
"libc",
|
||||
"log",
|
||||
"memmap2",
|
||||
"mio 1.999.999",
|
||||
"mio",
|
||||
"scopeguard",
|
||||
"serde",
|
||||
"serde_bytes",
|
||||
"serde_derive",
|
||||
"slab",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -1048,7 +1048,7 @@ dependencies = [
|
||||
"unic-langid",
|
||||
"uuid",
|
||||
"warp",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
"yaml-rust",
|
||||
"zip",
|
||||
]
|
||||
@ -1702,7 +1702,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a258e46cdc063eb8519c00b9fc845fc47bcfca4130e2f08e88665ceda8474245"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3761,20 +3761,15 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "0.8.8"
|
||||
source = "git+https://github.com/glandium/mio?rev=9a2ef335c366044ffe73b1c4acabe50a1daefe05#9a2ef335c366044ffe73b1c4acabe50a1daefe05"
|
||||
version = "1.0.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4"
|
||||
dependencies = [
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"log",
|
||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.999.999"
|
||||
dependencies = [
|
||||
"mio 0.8.8",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -3893,7 +3888,7 @@ dependencies = [
|
||||
"lmdb-rkv-sys",
|
||||
"log",
|
||||
"memchr",
|
||||
"mio 0.8.8",
|
||||
"mio",
|
||||
"nom",
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
@ -3926,7 +3921,7 @@ dependencies = [
|
||||
"url",
|
||||
"uuid",
|
||||
"winapi",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
"xml-rs",
|
||||
"yoke",
|
||||
"zerofrom",
|
||||
@ -3986,7 +3981,7 @@ dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
"uuid",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4689,7 +4684,7 @@ dependencies = [
|
||||
"mozilla-central-workspace-hack",
|
||||
"scroll",
|
||||
"thiserror",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -4814,7 +4809,7 @@ dependencies = [
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2 0.5.7",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5146,7 +5141,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5480,7 +5475,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce305eb0b4296696835b71df73eb912e0f1ffd2556a501fcede6e0c50349191c"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5801,7 +5796,7 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"fastrand",
|
||||
"rustix",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5947,27 +5942,25 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.29.1"
|
||||
version = "1.39.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "532826ff75199d5833b9d2c5fe410f29235e25704ee5f0ef599fb51c21f4a4da"
|
||||
checksum = "daa4fb1bc778bd6f04cbfc4bb2d06a7396a8f299dc33ea1900cedaa316f467b1"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
"backtrace",
|
||||
"bytes",
|
||||
"libc",
|
||||
"mio 0.8.8",
|
||||
"num_cpus",
|
||||
"mio",
|
||||
"pin-project-lite",
|
||||
"socket2 0.4.999",
|
||||
"socket2 0.5.7",
|
||||
"tokio-macros",
|
||||
"windows-sys 0.48.999",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tokio-macros"
|
||||
version = "2.1.0"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"
|
||||
checksum = "693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
@ -6924,13 +6917,6 @@ dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.48.999"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
|
@ -111,9 +111,6 @@ mozilla-central-workspace-hack = { path = "build/workspace-hack" }
|
||||
# crate, which we don't really need as we require MSVC anyways.
|
||||
windows-targets = { path = "build/rust/windows-targets" }
|
||||
|
||||
# Patch windows-sys from 0.48.0 to 0.52.0
|
||||
windows-sys = { path = "build/rust/windows-sys" }
|
||||
|
||||
# Patch windows to use a non-vendored local copy of the crate.
|
||||
windows = { path = "build/rust/windows" }
|
||||
|
||||
@ -222,11 +219,6 @@ tabs = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6
|
||||
viaduct = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6f2f8acd38579bd3142fecda9272957b72" }
|
||||
webext-storage = { git = "https://github.com/mozilla/application-services", rev = "8fd08c6f2f8acd38579bd3142fecda9272957b72" }
|
||||
|
||||
# Patch mio 0.8.8 to use windows-sys 0.52 (backport https://github.com/tokio-rs/mio/commit/eea9e3e0c469480e5c59c01e6c3c7e5fd88f0848)
|
||||
mio_0_8 = { package = "mio", git = "https://github.com/glandium/mio", rev = "9a2ef335c366044ffe73b1c4acabe50a1daefe05" }
|
||||
# Downgrade mio 1.0 to 0.8 until tokio is upgraded to use mio 1.0.
|
||||
mio = { path = "build/rust/mio" }
|
||||
|
||||
# Patch `gpu-descriptor` 0.3.0 to remove unnecessary `allocator-api2` dep.:
|
||||
# Still waiting for the now-merged <https://github.com/zakarumych/gpu-descriptor/pull/40> to be released.
|
||||
gpu-descriptor = { git = "https://github.com/zakarumych/gpu-descriptor", rev = "7b71a4e47c81903ad75e2c53deb5ab1310f6ff4d" }
|
||||
|
@ -1,19 +0,0 @@
|
||||
[package]
|
||||
name = "mio"
|
||||
version = "1.999.999"
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies.mio]
|
||||
default-features = false
|
||||
version = "0.8"
|
||||
|
||||
[features]
|
||||
default = ["mio/default"]
|
||||
log = ["mio/log"]
|
||||
net = ["mio/net"]
|
||||
os-ext = ["mio/os-ext"]
|
||||
os-poll = ["mio/os-poll"]
|
@ -1,5 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
pub use mio::*;
|
@ -1,232 +0,0 @@
|
||||
[package]
|
||||
name = "windows-sys"
|
||||
version = "0.48.999"
|
||||
edition = "2018"
|
||||
license = "MPL-2.0"
|
||||
|
||||
[lib]
|
||||
path = "lib.rs"
|
||||
|
||||
[dependencies.windows-sys]
|
||||
version = "0.52"
|
||||
default-features = false
|
||||
|
||||
[features]
|
||||
Wdk = ["windows-sys/Wdk"]
|
||||
Wdk_System = ["windows-sys/Wdk_System"]
|
||||
Wdk_System_OfflineRegistry = ["windows-sys/Wdk_System_OfflineRegistry"]
|
||||
Win32 = ["windows-sys/Win32"]
|
||||
Win32_Data = ["windows-sys/Win32_Data"]
|
||||
Win32_Data_HtmlHelp = ["windows-sys/Win32_Data_HtmlHelp"]
|
||||
Win32_Data_RightsManagement = ["windows-sys/Win32_Data_RightsManagement"]
|
||||
Win32_Devices = ["windows-sys/Win32_Devices"]
|
||||
Win32_Devices_AllJoyn = ["windows-sys/Win32_Devices_AllJoyn"]
|
||||
Win32_Devices_BiometricFramework = ["windows-sys/Win32_Devices_BiometricFramework"]
|
||||
Win32_Devices_Bluetooth = ["windows-sys/Win32_Devices_Bluetooth"]
|
||||
Win32_Devices_Communication = ["windows-sys/Win32_Devices_Communication"]
|
||||
Win32_Devices_DeviceAndDriverInstallation = ["windows-sys/Win32_Devices_DeviceAndDriverInstallation"]
|
||||
Win32_Devices_DeviceQuery = ["windows-sys/Win32_Devices_DeviceQuery"]
|
||||
Win32_Devices_Display = ["windows-sys/Win32_Devices_Display"]
|
||||
Win32_Devices_Enumeration = ["windows-sys/Win32_Devices_Enumeration"]
|
||||
Win32_Devices_Enumeration_Pnp = ["windows-sys/Win32_Devices_Enumeration_Pnp"]
|
||||
Win32_Devices_Fax = ["windows-sys/Win32_Devices_Fax"]
|
||||
Win32_Devices_HumanInterfaceDevice = ["windows-sys/Win32_Devices_HumanInterfaceDevice"]
|
||||
Win32_Devices_PortableDevices = ["windows-sys/Win32_Devices_PortableDevices"]
|
||||
Win32_Devices_Properties = ["windows-sys/Win32_Devices_Properties"]
|
||||
Win32_Devices_Pwm = ["windows-sys/Win32_Devices_Pwm"]
|
||||
Win32_Devices_Sensors = ["windows-sys/Win32_Devices_Sensors"]
|
||||
Win32_Devices_SerialCommunication = ["windows-sys/Win32_Devices_SerialCommunication"]
|
||||
Win32_Devices_Tapi = ["windows-sys/Win32_Devices_Tapi"]
|
||||
Win32_Devices_Usb = ["windows-sys/Win32_Devices_Usb"]
|
||||
Win32_Devices_WebServicesOnDevices = ["windows-sys/Win32_Devices_WebServicesOnDevices"]
|
||||
Win32_Foundation = ["windows-sys/Win32_Foundation"]
|
||||
Win32_Gaming = ["windows-sys/Win32_Gaming"]
|
||||
Win32_Globalization = ["windows-sys/Win32_Globalization"]
|
||||
Win32_Graphics = ["windows-sys/Win32_Graphics"]
|
||||
Win32_Graphics_Dwm = ["windows-sys/Win32_Graphics_Dwm"]
|
||||
Win32_Graphics_Gdi = ["windows-sys/Win32_Graphics_Gdi"]
|
||||
Win32_Graphics_Hlsl = ["windows-sys/Win32_Graphics_Hlsl"]
|
||||
Win32_Graphics_OpenGL = ["windows-sys/Win32_Graphics_OpenGL"]
|
||||
Win32_Graphics_Printing = ["windows-sys/Win32_Graphics_Printing"]
|
||||
Win32_Graphics_Printing_PrintTicket = ["windows-sys/Win32_Graphics_Printing_PrintTicket"]
|
||||
Win32_Management = ["windows-sys/Win32_Management"]
|
||||
Win32_Management_MobileDeviceManagementRegistration = ["windows-sys/Win32_Management_MobileDeviceManagementRegistration"]
|
||||
Win32_Media = ["windows-sys/Win32_Media"]
|
||||
Win32_Media_Audio = ["windows-sys/Win32_Media_Audio"]
|
||||
Win32_Media_DxMediaObjects = ["windows-sys/Win32_Media_DxMediaObjects"]
|
||||
Win32_Media_KernelStreaming = ["windows-sys/Win32_Media_KernelStreaming"]
|
||||
Win32_Media_Multimedia = ["windows-sys/Win32_Media_Multimedia"]
|
||||
Win32_Media_Streaming = ["windows-sys/Win32_Media_Streaming"]
|
||||
Win32_Media_WindowsMediaFormat = ["windows-sys/Win32_Media_WindowsMediaFormat"]
|
||||
Win32_NetworkManagement = ["windows-sys/Win32_NetworkManagement"]
|
||||
Win32_NetworkManagement_Dhcp = ["windows-sys/Win32_NetworkManagement_Dhcp"]
|
||||
Win32_NetworkManagement_Dns = ["windows-sys/Win32_NetworkManagement_Dns"]
|
||||
Win32_NetworkManagement_InternetConnectionWizard = ["windows-sys/Win32_NetworkManagement_InternetConnectionWizard"]
|
||||
Win32_NetworkManagement_IpHelper = ["windows-sys/Win32_NetworkManagement_IpHelper"]
|
||||
Win32_NetworkManagement_Multicast = ["windows-sys/Win32_NetworkManagement_Multicast"]
|
||||
Win32_NetworkManagement_Ndis = ["windows-sys/Win32_NetworkManagement_Ndis"]
|
||||
Win32_NetworkManagement_NetBios = ["windows-sys/Win32_NetworkManagement_NetBios"]
|
||||
Win32_NetworkManagement_NetManagement = ["windows-sys/Win32_NetworkManagement_NetManagement"]
|
||||
Win32_NetworkManagement_NetShell = ["windows-sys/Win32_NetworkManagement_NetShell"]
|
||||
Win32_NetworkManagement_NetworkDiagnosticsFramework = ["windows-sys/Win32_NetworkManagement_NetworkDiagnosticsFramework"]
|
||||
Win32_NetworkManagement_P2P = ["windows-sys/Win32_NetworkManagement_P2P"]
|
||||
Win32_NetworkManagement_QoS = ["windows-sys/Win32_NetworkManagement_QoS"]
|
||||
Win32_NetworkManagement_Rras = ["windows-sys/Win32_NetworkManagement_Rras"]
|
||||
Win32_NetworkManagement_Snmp = ["windows-sys/Win32_NetworkManagement_Snmp"]
|
||||
Win32_NetworkManagement_WNet = ["windows-sys/Win32_NetworkManagement_WNet"]
|
||||
Win32_NetworkManagement_WebDav = ["windows-sys/Win32_NetworkManagement_WebDav"]
|
||||
Win32_NetworkManagement_WiFi = ["windows-sys/Win32_NetworkManagement_WiFi"]
|
||||
Win32_NetworkManagement_WindowsConnectionManager = ["windows-sys/Win32_NetworkManagement_WindowsConnectionManager"]
|
||||
Win32_NetworkManagement_WindowsFilteringPlatform = ["windows-sys/Win32_NetworkManagement_WindowsFilteringPlatform"]
|
||||
Win32_NetworkManagement_WindowsFirewall = ["windows-sys/Win32_NetworkManagement_WindowsFirewall"]
|
||||
Win32_NetworkManagement_WindowsNetworkVirtualization = ["windows-sys/Win32_NetworkManagement_WindowsNetworkVirtualization"]
|
||||
Win32_Networking = ["windows-sys/Win32_Networking"]
|
||||
Win32_Networking_ActiveDirectory = ["windows-sys/Win32_Networking_ActiveDirectory"]
|
||||
Win32_Networking_Clustering = ["windows-sys/Win32_Networking_Clustering"]
|
||||
Win32_Networking_HttpServer = ["windows-sys/Win32_Networking_HttpServer"]
|
||||
Win32_Networking_Ldap = ["windows-sys/Win32_Networking_Ldap"]
|
||||
Win32_Networking_WebSocket = ["windows-sys/Win32_Networking_WebSocket"]
|
||||
Win32_Networking_WinHttp = ["windows-sys/Win32_Networking_WinHttp"]
|
||||
Win32_Networking_WinInet = ["windows-sys/Win32_Networking_WinInet"]
|
||||
Win32_Networking_WinSock = ["windows-sys/Win32_Networking_WinSock"]
|
||||
Win32_Networking_WindowsWebServices = ["windows-sys/Win32_Networking_WindowsWebServices"]
|
||||
Win32_Security = ["windows-sys/Win32_Security"]
|
||||
Win32_Security_AppLocker = ["windows-sys/Win32_Security_AppLocker"]
|
||||
Win32_Security_Authentication = ["windows-sys/Win32_Security_Authentication"]
|
||||
Win32_Security_Authentication_Identity = ["windows-sys/Win32_Security_Authentication_Identity"]
|
||||
Win32_Security_Authorization = ["windows-sys/Win32_Security_Authorization"]
|
||||
Win32_Security_Credentials = ["windows-sys/Win32_Security_Credentials"]
|
||||
Win32_Security_Cryptography = ["windows-sys/Win32_Security_Cryptography"]
|
||||
Win32_Security_Cryptography_Catalog = ["windows-sys/Win32_Security_Cryptography_Catalog"]
|
||||
Win32_Security_Cryptography_Certificates = ["windows-sys/Win32_Security_Cryptography_Certificates"]
|
||||
Win32_Security_Cryptography_Sip = ["windows-sys/Win32_Security_Cryptography_Sip"]
|
||||
Win32_Security_Cryptography_UI = ["windows-sys/Win32_Security_Cryptography_UI"]
|
||||
Win32_Security_DiagnosticDataQuery = ["windows-sys/Win32_Security_DiagnosticDataQuery"]
|
||||
Win32_Security_DirectoryServices = ["windows-sys/Win32_Security_DirectoryServices"]
|
||||
Win32_Security_EnterpriseData = ["windows-sys/Win32_Security_EnterpriseData"]
|
||||
Win32_Security_ExtensibleAuthenticationProtocol = ["windows-sys/Win32_Security_ExtensibleAuthenticationProtocol"]
|
||||
Win32_Security_Isolation = ["windows-sys/Win32_Security_Isolation"]
|
||||
Win32_Security_LicenseProtection = ["windows-sys/Win32_Security_LicenseProtection"]
|
||||
Win32_Security_NetworkAccessProtection = ["windows-sys/Win32_Security_NetworkAccessProtection"]
|
||||
Win32_Security_WinTrust = ["windows-sys/Win32_Security_WinTrust"]
|
||||
Win32_Security_WinWlx = ["windows-sys/Win32_Security_WinWlx"]
|
||||
Win32_Storage = ["windows-sys/Win32_Storage"]
|
||||
Win32_Storage_Cabinets = ["windows-sys/Win32_Storage_Cabinets"]
|
||||
Win32_Storage_CloudFilters = ["windows-sys/Win32_Storage_CloudFilters"]
|
||||
Win32_Storage_Compression = ["windows-sys/Win32_Storage_Compression"]
|
||||
Win32_Storage_DistributedFileSystem = ["windows-sys/Win32_Storage_DistributedFileSystem"]
|
||||
Win32_Storage_FileHistory = ["windows-sys/Win32_Storage_FileHistory"]
|
||||
Win32_Storage_FileSystem = ["windows-sys/Win32_Storage_FileSystem"]
|
||||
Win32_Storage_Imapi = ["windows-sys/Win32_Storage_Imapi"]
|
||||
Win32_Storage_IndexServer = ["windows-sys/Win32_Storage_IndexServer"]
|
||||
Win32_Storage_InstallableFileSystems = ["windows-sys/Win32_Storage_InstallableFileSystems"]
|
||||
Win32_Storage_IscsiDisc = ["windows-sys/Win32_Storage_IscsiDisc"]
|
||||
Win32_Storage_Jet = ["windows-sys/Win32_Storage_Jet"]
|
||||
Win32_Storage_OfflineFiles = ["windows-sys/Win32_Storage_OfflineFiles"]
|
||||
Win32_Storage_OperationRecorder = ["windows-sys/Win32_Storage_OperationRecorder"]
|
||||
Win32_Storage_Packaging = ["windows-sys/Win32_Storage_Packaging"]
|
||||
Win32_Storage_Packaging_Appx = ["windows-sys/Win32_Storage_Packaging_Appx"]
|
||||
Win32_Storage_ProjectedFileSystem = ["windows-sys/Win32_Storage_ProjectedFileSystem"]
|
||||
Win32_Storage_StructuredStorage = ["windows-sys/Win32_Storage_StructuredStorage"]
|
||||
Win32_Storage_Vhd = ["windows-sys/Win32_Storage_Vhd"]
|
||||
Win32_Storage_Xps = ["windows-sys/Win32_Storage_Xps"]
|
||||
Win32_System = ["windows-sys/Win32_System"]
|
||||
Win32_System_AddressBook = ["windows-sys/Win32_System_AddressBook"]
|
||||
Win32_System_Antimalware = ["windows-sys/Win32_System_Antimalware"]
|
||||
Win32_System_ApplicationInstallationAndServicing = ["windows-sys/Win32_System_ApplicationInstallationAndServicing"]
|
||||
Win32_System_ApplicationVerifier = ["windows-sys/Win32_System_ApplicationVerifier"]
|
||||
Win32_System_ClrHosting = ["windows-sys/Win32_System_ClrHosting"]
|
||||
Win32_System_Com = ["windows-sys/Win32_System_Com"]
|
||||
Win32_System_Com_Marshal = ["windows-sys/Win32_System_Com_Marshal"]
|
||||
Win32_System_Com_StructuredStorage = ["windows-sys/Win32_System_Com_StructuredStorage"]
|
||||
Win32_System_Com_Urlmon = ["windows-sys/Win32_System_Com_Urlmon"]
|
||||
Win32_System_ComponentServices = ["windows-sys/Win32_System_ComponentServices"]
|
||||
Win32_System_Console = ["windows-sys/Win32_System_Console"]
|
||||
Win32_System_CorrelationVector = ["windows-sys/Win32_System_CorrelationVector"]
|
||||
Win32_System_DataExchange = ["windows-sys/Win32_System_DataExchange"]
|
||||
Win32_System_DeploymentServices = ["windows-sys/Win32_System_DeploymentServices"]
|
||||
Win32_System_DeveloperLicensing = ["windows-sys/Win32_System_DeveloperLicensing"]
|
||||
Win32_System_Diagnostics = ["windows-sys/Win32_System_Diagnostics"]
|
||||
Win32_System_Diagnostics_Ceip = ["windows-sys/Win32_System_Diagnostics_Ceip"]
|
||||
Win32_System_Diagnostics_Debug = ["windows-sys/Win32_System_Diagnostics_Debug"]
|
||||
Win32_System_Diagnostics_Debug_Extensions = ["windows-sys/Win32_System_Diagnostics_Debug_Extensions"]
|
||||
Win32_System_Diagnostics_Etw = ["windows-sys/Win32_System_Diagnostics_Etw"]
|
||||
Win32_System_Diagnostics_ProcessSnapshotting = ["windows-sys/Win32_System_Diagnostics_ProcessSnapshotting"]
|
||||
Win32_System_Diagnostics_ToolHelp = ["windows-sys/Win32_System_Diagnostics_ToolHelp"]
|
||||
Win32_System_DistributedTransactionCoordinator = ["windows-sys/Win32_System_DistributedTransactionCoordinator"]
|
||||
Win32_System_Environment = ["windows-sys/Win32_System_Environment"]
|
||||
Win32_System_ErrorReporting = ["windows-sys/Win32_System_ErrorReporting"]
|
||||
Win32_System_EventCollector = ["windows-sys/Win32_System_EventCollector"]
|
||||
Win32_System_EventLog = ["windows-sys/Win32_System_EventLog"]
|
||||
Win32_System_EventNotificationService = ["windows-sys/Win32_System_EventNotificationService"]
|
||||
Win32_System_GroupPolicy = ["windows-sys/Win32_System_GroupPolicy"]
|
||||
Win32_System_HostCompute = ["windows-sys/Win32_System_HostCompute"]
|
||||
Win32_System_HostComputeNetwork = ["windows-sys/Win32_System_HostComputeNetwork"]
|
||||
Win32_System_HostComputeSystem = ["windows-sys/Win32_System_HostComputeSystem"]
|
||||
Win32_System_Hypervisor = ["windows-sys/Win32_System_Hypervisor"]
|
||||
Win32_System_IO = ["windows-sys/Win32_System_IO"]
|
||||
Win32_System_Iis = ["windows-sys/Win32_System_Iis"]
|
||||
Win32_System_Ioctl = ["windows-sys/Win32_System_Ioctl"]
|
||||
Win32_System_JobObjects = ["windows-sys/Win32_System_JobObjects"]
|
||||
Win32_System_Js = ["windows-sys/Win32_System_Js"]
|
||||
Win32_System_Kernel = ["windows-sys/Win32_System_Kernel"]
|
||||
Win32_System_LibraryLoader = ["windows-sys/Win32_System_LibraryLoader"]
|
||||
Win32_System_Mailslots = ["windows-sys/Win32_System_Mailslots"]
|
||||
Win32_System_Mapi = ["windows-sys/Win32_System_Mapi"]
|
||||
Win32_System_Memory = ["windows-sys/Win32_System_Memory"]
|
||||
Win32_System_Memory_NonVolatile = ["windows-sys/Win32_System_Memory_NonVolatile"]
|
||||
Win32_System_MessageQueuing = ["windows-sys/Win32_System_MessageQueuing"]
|
||||
Win32_System_MixedReality = ["windows-sys/Win32_System_MixedReality"]
|
||||
Win32_System_Ole = ["windows-sys/Win32_System_Ole"]
|
||||
Win32_System_PasswordManagement = ["windows-sys/Win32_System_PasswordManagement"]
|
||||
Win32_System_Performance = ["windows-sys/Win32_System_Performance"]
|
||||
Win32_System_Performance_HardwareCounterProfiling = ["windows-sys/Win32_System_Performance_HardwareCounterProfiling"]
|
||||
Win32_System_Pipes = ["windows-sys/Win32_System_Pipes"]
|
||||
Win32_System_Power = ["windows-sys/Win32_System_Power"]
|
||||
Win32_System_ProcessStatus = ["windows-sys/Win32_System_ProcessStatus"]
|
||||
Win32_System_Recovery = ["windows-sys/Win32_System_Recovery"]
|
||||
Win32_System_Registry = ["windows-sys/Win32_System_Registry"]
|
||||
Win32_System_RemoteDesktop = ["windows-sys/Win32_System_RemoteDesktop"]
|
||||
Win32_System_RemoteManagement = ["windows-sys/Win32_System_RemoteManagement"]
|
||||
Win32_System_RestartManager = ["windows-sys/Win32_System_RestartManager"]
|
||||
Win32_System_Restore = ["windows-sys/Win32_System_Restore"]
|
||||
Win32_System_Rpc = ["windows-sys/Win32_System_Rpc"]
|
||||
Win32_System_Search = ["windows-sys/Win32_System_Search"]
|
||||
Win32_System_Search_Common = ["windows-sys/Win32_System_Search_Common"]
|
||||
Win32_System_SecurityCenter = ["windows-sys/Win32_System_SecurityCenter"]
|
||||
Win32_System_Services = ["windows-sys/Win32_System_Services"]
|
||||
Win32_System_SetupAndMigration = ["windows-sys/Win32_System_SetupAndMigration"]
|
||||
Win32_System_Shutdown = ["windows-sys/Win32_System_Shutdown"]
|
||||
Win32_System_StationsAndDesktops = ["windows-sys/Win32_System_StationsAndDesktops"]
|
||||
Win32_System_SubsystemForLinux = ["windows-sys/Win32_System_SubsystemForLinux"]
|
||||
Win32_System_SystemInformation = ["windows-sys/Win32_System_SystemInformation"]
|
||||
Win32_System_SystemServices = ["windows-sys/Win32_System_SystemServices"]
|
||||
Win32_System_Threading = ["windows-sys/Win32_System_Threading"]
|
||||
Win32_System_Time = ["windows-sys/Win32_System_Time"]
|
||||
Win32_System_TpmBaseServices = ["windows-sys/Win32_System_TpmBaseServices"]
|
||||
Win32_System_UserAccessLogging = ["windows-sys/Win32_System_UserAccessLogging"]
|
||||
Win32_System_VirtualDosMachines = ["windows-sys/Win32_System_VirtualDosMachines"]
|
||||
Win32_System_WindowsProgramming = ["windows-sys/Win32_System_WindowsProgramming"]
|
||||
Win32_System_Wmi = ["windows-sys/Win32_System_Wmi"]
|
||||
Win32_UI = ["windows-sys/Win32_UI"]
|
||||
Win32_UI_Accessibility = ["windows-sys/Win32_UI_Accessibility"]
|
||||
Win32_UI_ColorSystem = ["windows-sys/Win32_UI_ColorSystem"]
|
||||
Win32_UI_Controls = ["windows-sys/Win32_UI_Controls"]
|
||||
Win32_UI_Controls_Dialogs = ["windows-sys/Win32_UI_Controls_Dialogs"]
|
||||
Win32_UI_HiDpi = ["windows-sys/Win32_UI_HiDpi"]
|
||||
Win32_UI_Input = ["windows-sys/Win32_UI_Input"]
|
||||
Win32_UI_Input_Ime = ["windows-sys/Win32_UI_Input_Ime"]
|
||||
Win32_UI_Input_KeyboardAndMouse = ["windows-sys/Win32_UI_Input_KeyboardAndMouse"]
|
||||
Win32_UI_Input_Pointer = ["windows-sys/Win32_UI_Input_Pointer"]
|
||||
Win32_UI_Input_Touch = ["windows-sys/Win32_UI_Input_Touch"]
|
||||
Win32_UI_Input_XboxController = ["windows-sys/Win32_UI_Input_XboxController"]
|
||||
Win32_UI_InteractionContext = ["windows-sys/Win32_UI_InteractionContext"]
|
||||
Win32_UI_Magnification = ["windows-sys/Win32_UI_Magnification"]
|
||||
Win32_UI_Shell = ["windows-sys/Win32_UI_Shell"]
|
||||
Win32_UI_Shell_PropertiesSystem = ["windows-sys/Win32_UI_Shell_PropertiesSystem"]
|
||||
Win32_UI_TabletPC = ["windows-sys/Win32_UI_TabletPC"]
|
||||
Win32_UI_TextServices = ["windows-sys/Win32_UI_TextServices"]
|
||||
Win32_UI_WindowsAndMessaging = ["windows-sys/Win32_UI_WindowsAndMessaging"]
|
||||
Win32_Web = ["windows-sys/Win32_Web"]
|
||||
Win32_Web_InternetExplorer = ["windows-sys/Win32_Web_InternetExplorer"]
|
||||
default = ["windows-sys/default"]
|
@ -1,5 +0,0 @@
|
||||
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||
|
||||
pub use windows_sys::*;
|
@ -43,7 +43,7 @@ indexmap = { version = "2", default-features = false, features = ["serde", "std"
|
||||
libc = { version = "0.2", features = ["extra_traits"] }
|
||||
lmdb-rkv-sys = { version = "0.11", default-features = false, features = ["mdb_idl_logn_9"], optional = true }
|
||||
log = { version = "0.4", features = ["release_max_level_info", "std"], optional = true }
|
||||
mio = { version = "0.8", features = ["log"], optional = true }
|
||||
mio = { version = "1", features = ["log"], optional = true }
|
||||
num-integer = { version = "0.1", optional = true }
|
||||
num-traits = { version = "0.2", features = ["i128", "libm"], optional = true }
|
||||
once_cell = { version = "1", optional = true }
|
||||
@ -59,7 +59,7 @@ stable_deref_trait = { version = "1", features = ["std"], optional = true }
|
||||
strsim = { version = "0.10", optional = true }
|
||||
time = { version = "0.3", features = ["macros", "parsing", "serde"], optional = true }
|
||||
tinystr = { version = "0.7", features = ["zerovec"], optional = true }
|
||||
tokio = { version = "1", features = ["fs", "macros", "num_cpus", "rt-multi-thread"], optional = true }
|
||||
tokio = { version = "1", features = ["fs", "macros", "rt-multi-thread"], optional = true }
|
||||
tokio-util = { version = "0.7", features = ["io"], optional = true }
|
||||
tracing = { version = "0.1", features = ["log"], optional = true }
|
||||
unic-langid = { version = "0.9", features = ["likelysubtags"], optional = true }
|
||||
|
@ -3018,8 +3018,7 @@ delta = "0.8.0 -> 0.8.6"
|
||||
[[audits.mio]]
|
||||
who = "Mike Hommey <mh+mozilla@glandium.org>"
|
||||
criteria = "safe-to-deploy"
|
||||
delta = "0.8.8 -> 0.8.8@git:9a2ef335c366044ffe73b1c4acabe50a1daefe05"
|
||||
importable = false
|
||||
delta = "0.8.8 -> 1.0.1"
|
||||
|
||||
[[audits.moz_cbor]]
|
||||
who = "Bobby Holley <bobbyholley@gmail.com>"
|
||||
@ -5739,11 +5738,17 @@ user-id = 3618 # David Tolnay (dtolnay)
|
||||
start = "2020-06-16"
|
||||
end = "2024-04-25"
|
||||
|
||||
[[trusted.tokio]]
|
||||
criteria = "safe-to-run"
|
||||
user-id = 6741 # Alice Ryhl (Darksonn)
|
||||
start = "2020-12-25"
|
||||
end = "2025-07-30"
|
||||
|
||||
[[trusted.tokio-macros]]
|
||||
criteria = "safe-to-deploy"
|
||||
user-id = 6741 # Alice Ryhl (Darksonn)
|
||||
start = "2020-10-26"
|
||||
end = "2024-05-05"
|
||||
end = "2025-07-30"
|
||||
|
||||
[[trusted.tokio-util]]
|
||||
criteria = "safe-to-deploy"
|
||||
|
@ -110,10 +110,6 @@ notes = "This is a first-party crate which is also published to crates.io. We ce
|
||||
audit-as-crates-io = true
|
||||
notes = "This is a pinned version of the upstream code, presumably to get a fix that hadn't been released yet. We should consider switching to the latest official release."
|
||||
|
||||
[policy."mio:0.8.8@git:9a2ef335c366044ffe73b1c4acabe50a1daefe05"]
|
||||
audit-as-crates-io = true
|
||||
notes = "This is 0.8.8 + https://github.com/tokio-rs/mio/commit/eea9e3e0c469480e5c59c01e6c3c7e5fd88f0848."
|
||||
|
||||
[policy.mozbuild]
|
||||
audit-as-crates-io = false
|
||||
notes = "The crates.io version of this is just a placeholder to allow public crates to depend on mozbuild."
|
||||
|
@ -594,6 +594,20 @@ user-id = 3618
|
||||
user-login = "dtolnay"
|
||||
user-name = "David Tolnay"
|
||||
|
||||
[[publisher.tokio]]
|
||||
version = "1.39.2"
|
||||
when = "2024-07-27"
|
||||
user-id = 6741
|
||||
user-login = "Darksonn"
|
||||
user-name = "Alice Ryhl"
|
||||
|
||||
[[publisher.tokio-macros]]
|
||||
version = "2.4.0"
|
||||
when = "2024-07-23"
|
||||
user-id = 6741
|
||||
user-login = "Darksonn"
|
||||
user-name = "Alice Ryhl"
|
||||
|
||||
[[publisher.tokio-util]]
|
||||
version = "0.7.2"
|
||||
when = "2022-05-15"
|
||||
|
2
third_party/rust/mio/.cargo-checksum.json
vendored
2
third_party/rust/mio/.cargo-checksum.json
vendored
File diff suppressed because one or more lines are too long
102
third_party/rust/mio/CHANGELOG.md
vendored
102
third_party/rust/mio/CHANGELOG.md
vendored
@ -1,3 +1,103 @@
|
||||
# 1.0.1
|
||||
|
||||
* Added Fuchsia support
|
||||
(https://github.com/tokio-rs/mio/pull/1811).
|
||||
* Added GNU/Hurd support
|
||||
(https://github.com/tokio-rs/mio/pull/1816).
|
||||
* Fixed an issue where accepting on a UDS socket without sometime pass an address
|
||||
with a NULL byte to SocketAddr::from_pathname
|
||||
(https://github.com/tokio-rs/mio/pull/1817).
|
||||
* Internal cleanups that should make the `cfg` sitations easier to follow
|
||||
(https://github.com/tokio-rs/mio/pull/1812,
|
||||
https://github.com/tokio-rs/mio/pull/1813).
|
||||
|
||||
# 1.0
|
||||
|
||||
With v1 Mio is able to bump its MSRV to 1.70, allowing us to implement I/O
|
||||
safety traits (https://github.com/rust-lang/rust/issues/87074) and replace
|
||||
`SocketAddr` with the version found in the standard library.
|
||||
|
||||
## Added
|
||||
|
||||
* Implement `AsFd` for`TcpListener`, `TcpStream`, `UdpSocket`, `UnixDatagram`,
|
||||
`UnixListener`, `UnixStream`, `pipe::Receiver` and `pipe::Sender`
|
||||
(https://github.com/tokio-rs/mio/pull/1749, https://github.com/tokio-rs/mio/pull/1797).
|
||||
* Implement `From` for `TcpListener`, `TcpStream`, `UdpSocket`, `UnixDatagram`,
|
||||
`UnixListener`, and `UnixStream` for their standard library counterpart
|
||||
(https://github.com/tokio-rs/mio/pull/1767).
|
||||
* Add support for abstract namespaces on Android
|
||||
(https://github.com/tokio-rs/mio/pull/1749).
|
||||
* Add support for QNX OS
|
||||
(https://github.com/tokio-rs/mio/pull/1766,
|
||||
https://github.com/tokio-rs/mio/pull/1800).
|
||||
* Add support for Apple visionOS
|
||||
(https://github.com/tokio-rs/mio/pull/1795).
|
||||
* Support for Haiku
|
||||
(https://github.com/tokio-rs/mio/pull/1807).
|
||||
|
||||
## Removed
|
||||
|
||||
* The `SocketAddr` type is removed in favour of `std::os::unix::net::SocketAddr`
|
||||
(https://github.com/tokio-rs/mio/pull/1760). All methods on Mio's version
|
||||
should exist on the version in the standard library.
|
||||
|
||||
## Changes
|
||||
|
||||
* MSRV was updated to 1.74, updating to Rust edition edition
|
||||
(https://github.com/tokio-rs/mio/pull/1733).
|
||||
* `UnixDatagram::{local_addr,peer_addr,bind_addr,recv_from}`,
|
||||
`UnixListener::{local_addr,bind_addr,accept}` and
|
||||
`UnixStream::{local_addr,peer_addr,connect_addr}` return and/or use
|
||||
`std::os::unix::net::SocketAddr` instead of Mio's own `SocketAddr` type
|
||||
(https://github.com/tokio-rs/mio/pull/1760).
|
||||
* Use `OwnedFd` internally for `Poll` where possible
|
||||
(https://github.com/tokio-rs/mio/pull/1749).
|
||||
* Support ESP-IDF and Hermit without cfg flags
|
||||
(https://github.com/tokio-rs/mio/pull/1789,
|
||||
https://github.com/tokio-rs/mio/pull/1802,
|
||||
https://github.com/tokio-rs/mio/pull/1802).
|
||||
* Updated windows-sys to v0.52
|
||||
(https://github.com/tokio-rs/mio/pull/1668).
|
||||
|
||||
# 0.8.11
|
||||
|
||||
* Fix receiving IOCP events after deregistering a Windows named pipe
|
||||
(https://github.com/tokio-rs/mio/pull/1760, backport pr:
|
||||
https://github.com/tokio-rs/mio/pull/1761).
|
||||
|
||||
# 0.8.10
|
||||
|
||||
## Added
|
||||
|
||||
* Solaris support
|
||||
(https://github.com/tokio-rs/mio/pull/1724).
|
||||
|
||||
# 0.8.9
|
||||
|
||||
## Added
|
||||
|
||||
* ESP-IDF framework support
|
||||
(https://github.com/tokio-rs/mio/pull/1692).
|
||||
* AIX operating system support
|
||||
(https://github.com/tokio-rs/mio/pull/1704).
|
||||
* Vita support
|
||||
(https://github.com/tokio-rs/mio/pull/1721).
|
||||
* `{UnixListener,UnixStream}:bind_addr`
|
||||
(https://github.com/tokio-rs/mio/pull/1630).
|
||||
* `mio_unsupported_force_poll_poll` and `mio_unsupported_force_waker_pipe`
|
||||
**unsupported** configuration flags to force a specific poll or waker
|
||||
implementation
|
||||
(https://github.com/tokio-rs/mio/pull/1684,
|
||||
https://github.com/tokio-rs/mio/pull/1685,
|
||||
https://github.com/tokio-rs/mio/pull/1692).
|
||||
|
||||
## Fixed
|
||||
|
||||
* The `pipe(2)` based waker (swapped file descriptors)
|
||||
(https://github.com/tokio-rs/mio/pull/1722).
|
||||
* The duplicate waker check to work correctly with cloned `Registry`s.
|
||||
(https://github.com/tokio-rs/mio/pull/1706).
|
||||
|
||||
# 0.8.8
|
||||
|
||||
## Fixed
|
||||
@ -400,7 +500,7 @@ information.
|
||||
at least `event::Source` and `Poll`.
|
||||
* Mio now uses Rust 2018 and rustfmt for all code.
|
||||
* `Event` was changed to be a wrapper around the OS event. This means it can be
|
||||
significantly larger on some OSes.
|
||||
significantly larger on some OSs.
|
||||
* `Ready` was removed and replaced with various `is_*` methods on `Event`. For
|
||||
example instead checking for readable readiness using
|
||||
`Event::ready().is_readable()`, you would call `Event::is_readable()`.
|
||||
|
175
third_party/rust/mio/Cargo.lock
generated
vendored
Normal file
175
third_party/rust/mio/Cargo.lock
generated
vendored
Normal file
@ -0,0 +1,175 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "cfg-if"
|
||||
version = "1.0.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.9.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a12e6657c4c97ebab115a42dcee77225f7f482cdd841cf7088c657a42e9e00e7"
|
||||
dependencies = [
|
||||
"log",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "getrandom"
|
||||
version = "0.2.15"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "hermit-abi"
|
||||
version = "0.3.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d231dfb89cfffdbc30e7fc41579ed6066ad03abda9e567ccafae602b97ec5024"
|
||||
|
||||
[[package]]
|
||||
name = "libc"
|
||||
version = "0.2.155"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c"
|
||||
|
||||
[[package]]
|
||||
name = "log"
|
||||
version = "0.4.21"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c"
|
||||
|
||||
[[package]]
|
||||
name = "mio"
|
||||
version = "1.0.1"
|
||||
dependencies = [
|
||||
"env_logger",
|
||||
"hermit-abi",
|
||||
"libc",
|
||||
"log",
|
||||
"rand",
|
||||
"wasi",
|
||||
"windows-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.8.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"rand_chacha",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_chacha"
|
||||
version = "0.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88"
|
||||
dependencies = [
|
||||
"ppv-lite86",
|
||||
"rand_core",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rand_core"
|
||||
version = "0.6.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c"
|
||||
dependencies = [
|
||||
"getrandom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "wasi"
|
||||
version = "0.11.0+wasi-snapshot-preview1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
|
||||
|
||||
[[package]]
|
||||
name = "windows-sys"
|
||||
version = "0.52.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d"
|
||||
dependencies = [
|
||||
"windows-targets",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb"
|
||||
dependencies = [
|
||||
"windows_aarch64_gnullvm",
|
||||
"windows_aarch64_msvc",
|
||||
"windows_i686_gnu",
|
||||
"windows_i686_gnullvm",
|
||||
"windows_i686_msvc",
|
||||
"windows_x86_64_gnu",
|
||||
"windows_x86_64_gnullvm",
|
||||
"windows_x86_64_msvc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263"
|
||||
|
||||
[[package]]
|
||||
name = "windows_aarch64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_i686_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnu"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_gnullvm"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596"
|
||||
|
||||
[[package]]
|
||||
name = "windows_x86_64_msvc"
|
||||
version = "0.52.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0"
|
54
third_party/rust/mio/Cargo.toml
vendored
54
third_party/rust/mio/Cargo.toml
vendored
@ -10,14 +10,16 @@
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
edition = "2021"
|
||||
rust-version = "1.70"
|
||||
name = "mio"
|
||||
version = "0.8.8"
|
||||
version = "1.0.1"
|
||||
authors = [
|
||||
"Carl Lerche <me@carllerche.com>",
|
||||
"Thomas de Zeeuw <thomasdezeeuw@gmail.com>",
|
||||
"Tokio Contributors <team@tokio.rs>",
|
||||
]
|
||||
build = false
|
||||
include = [
|
||||
"Cargo.toml",
|
||||
"LICENSE",
|
||||
@ -26,6 +28,10 @@ include = [
|
||||
"src/**/*.rs",
|
||||
"examples/**/*.rs",
|
||||
]
|
||||
autobins = false
|
||||
autoexamples = false
|
||||
autotests = false
|
||||
autobenches = false
|
||||
description = "Lightweight non-blocking I/O."
|
||||
homepage = "https://github.com/tokio-rs/mio"
|
||||
readme = "README.md"
|
||||
@ -43,12 +49,14 @@ all-features = true
|
||||
rustdoc-args = [
|
||||
"--cfg",
|
||||
"docsrs",
|
||||
"--generate-link-to-definition",
|
||||
]
|
||||
targets = [
|
||||
"aarch64-apple-ios",
|
||||
"aarch64-linux-android",
|
||||
"wasm32-wasi",
|
||||
"x86_64-apple-darwin",
|
||||
"x86_64-pc-windows-gnu",
|
||||
"x86_64-pc-windows-msvc",
|
||||
"x86_64-unknown-dragonfly",
|
||||
"x86_64-unknown-freebsd",
|
||||
@ -56,6 +64,7 @@ targets = [
|
||||
"x86_64-unknown-linux-gnu",
|
||||
"x86_64-unknown-netbsd",
|
||||
"x86_64-unknown-openbsd",
|
||||
"x86_64-unknown-hermit",
|
||||
]
|
||||
|
||||
[package.metadata.playground]
|
||||
@ -65,15 +74,21 @@ features = [
|
||||
"net",
|
||||
]
|
||||
|
||||
[lib]
|
||||
name = "mio"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[example]]
|
||||
name = "tcp_server"
|
||||
name = "tcp_listenfd_server"
|
||||
path = "examples/tcp_listenfd_server.rs"
|
||||
required-features = [
|
||||
"os-poll",
|
||||
"net",
|
||||
]
|
||||
|
||||
[[example]]
|
||||
name = "tcp_listenfd_server"
|
||||
name = "tcp_server"
|
||||
path = "examples/tcp_server.rs"
|
||||
required-features = [
|
||||
"os-poll",
|
||||
"net",
|
||||
@ -81,6 +96,7 @@ required-features = [
|
||||
|
||||
[[example]]
|
||||
name = "udp_server"
|
||||
path = "examples/udp_server.rs"
|
||||
required-features = [
|
||||
"os-poll",
|
||||
"net",
|
||||
@ -90,13 +106,13 @@ required-features = [
|
||||
version = "0.4.8"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies]
|
||||
rand = "0.8"
|
||||
|
||||
[dev-dependencies.env_logger]
|
||||
version = "0.9.3"
|
||||
default-features = false
|
||||
|
||||
[dev-dependencies.rand]
|
||||
version = "0.8"
|
||||
|
||||
[features]
|
||||
default = ["log"]
|
||||
net = []
|
||||
@ -107,12 +123,18 @@ os-ext = [
|
||||
]
|
||||
os-poll = []
|
||||
|
||||
[target."cfg(target_os = \"wasi\")".dependencies]
|
||||
libc = "0.2.121"
|
||||
wasi = "0.11.0"
|
||||
[target.'cfg(target_os = "hermit")'.dependencies.libc]
|
||||
version = "0.3.9"
|
||||
package = "hermit-abi"
|
||||
|
||||
[target."cfg(unix)".dependencies]
|
||||
libc = "0.2.121"
|
||||
[target.'cfg(target_os = "wasi")'.dependencies.libc]
|
||||
version = "0.2.149"
|
||||
|
||||
[target.'cfg(target_os = "wasi")'.dependencies.wasi]
|
||||
version = "0.11.0"
|
||||
|
||||
[target."cfg(unix)".dependencies.libc]
|
||||
version = "0.2.149"
|
||||
|
||||
[target."cfg(windows)".dependencies.windows-sys]
|
||||
version = "0.52"
|
||||
@ -126,3 +148,11 @@ features = [
|
||||
"Win32_System_IO",
|
||||
"Win32_System_WindowsProgramming",
|
||||
]
|
||||
|
||||
[lints.rust.unexpected_cfgs]
|
||||
level = "warn"
|
||||
priority = 0
|
||||
check-cfg = [
|
||||
"cfg(mio_unsupported_force_poll_poll)",
|
||||
"cfg(mio_unsupported_force_waker_pipe)",
|
||||
]
|
||||
|
56
third_party/rust/mio/README.md
vendored
56
third_party/rust/mio/README.md
vendored
@ -20,8 +20,8 @@ overhead as possible over the OS abstractions.
|
||||
|
||||
**API documentation**
|
||||
|
||||
* [v1](https://docs.rs/mio/^1)
|
||||
* [v0.8](https://docs.rs/mio/^0.8)
|
||||
* [v0.7](https://docs.rs/mio/^0.7)
|
||||
|
||||
This is a low level library, if you are looking for something easier to get
|
||||
started with, see [Tokio](https://tokio.rs).
|
||||
@ -32,7 +32,7 @@ To use `mio`, first add this to your `Cargo.toml`:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
mio = "0.8"
|
||||
mio = "1"
|
||||
```
|
||||
|
||||
Next we can start using Mio. The following is quick introduction using
|
||||
@ -110,7 +110,7 @@ fn main() -> Result<(), Box<dyn Error>> {
|
||||
|
||||
## Features
|
||||
|
||||
* Non-blocking TCP, UDP
|
||||
* Non-blocking TCP, UDP, UDS
|
||||
* I/O event queue backed by epoll, kqueue, and IOCP
|
||||
* Zero allocations at runtime
|
||||
* Platform specific extensions
|
||||
@ -138,13 +138,13 @@ Currently supported platforms:
|
||||
* iOS
|
||||
* macOS
|
||||
|
||||
There are potentially others. If you find that Mio works on another
|
||||
platform, submit a PR to update the list!
|
||||
|
||||
Mio can handle interfacing with each of the event systems of the aforementioned
|
||||
platforms. The details of their implementation are further discussed in the
|
||||
`Poll` type of the API documentation (see above).
|
||||
|
||||
Mio generally supports the same versions of the above mentioned platforms as
|
||||
Rust the language (rustc) does, unless otherwise noted.
|
||||
|
||||
The Windows implementation for polling sockets is using the [wepoll] strategy.
|
||||
This uses the Windows AFD system to access socket readiness events.
|
||||
|
||||
@ -152,20 +152,54 @@ This uses the Windows AFD system to access socket readiness events.
|
||||
|
||||
### Unsupported
|
||||
|
||||
* Haiku, see [issue #1472]
|
||||
* Solaris, see [issue #1152]
|
||||
* Wine, see [issue #1444]
|
||||
|
||||
[issue #1472]: https://github.com/tokio-rs/mio/issues/1472
|
||||
[issue #1152]: https://github.com/tokio-rs/mio/issues/1152
|
||||
[issue #1444]: https://github.com/tokio-rs/mio/issues/1444
|
||||
|
||||
## MSRV Policy
|
||||
|
||||
The MSRV (Minimum Supported Rust Version) is fixed for a given minor (1.x)
|
||||
version. However it can be increased when bumping minor versions, i.e. going
|
||||
from 1.0 to 1.1 allows us to increase the MSRV. Users unable to increase their
|
||||
Rust version can use an older minor version instead. Below is a list of Mio versions
|
||||
and their MSRV:
|
||||
|
||||
* v0.8: Rust 1.46.
|
||||
* v1.0: Rust 1.70.
|
||||
|
||||
Note however that Mio also has dependencies, which might have different MSRV
|
||||
policies. We try to stick to the above policy when updating dependencies, but
|
||||
this is not always possible.
|
||||
|
||||
## Unsupported flags
|
||||
|
||||
Mio uses different implementations to support the same functionality depending
|
||||
on the platform. Mio generally uses the "best" implementation possible, where
|
||||
"best" usually means most efficient for Mio's use case. However this means that
|
||||
the implementation is often specific to a limited number of platforms, meaning
|
||||
we often have multiple implementations for the same functionality. In some cases
|
||||
it might be required to not use the "best" implementation, but another
|
||||
implementation Mio supports (on other platforms). **Mio does not officially
|
||||
support secondary implementations on platforms**, however we do have various cfg
|
||||
flags to force another implementation for these situations.
|
||||
|
||||
Current flags:
|
||||
* `mio_unsupported_force_poll_poll`, uses an implementation based on `poll(2)`
|
||||
for `mio::Poll`.
|
||||
* `mio_unsupported_force_waker_pipe`, uses an implementation based on `pipe(2)`
|
||||
for `mio::Waker`.
|
||||
|
||||
**Again, Mio does not officially supports this**. Furthermore these flags may
|
||||
disappear in the future.
|
||||
|
||||
## Community
|
||||
|
||||
A group of Mio users hang out on [Discord], this can be a good place to go for
|
||||
questions.
|
||||
questions. It's also possible to open a [new issue on GitHub] to ask questions,
|
||||
report bugs or suggest new features.
|
||||
|
||||
[Discord]: https://discord.gg/tokio
|
||||
[new issue on GitHub]: https://github.com/tokio-rs/mio/issues/new
|
||||
|
||||
## Contributing
|
||||
|
||||
|
@ -19,10 +19,8 @@ const DATA: &[u8] = b"Hello world!\n";
|
||||
|
||||
#[cfg(not(windows))]
|
||||
fn get_first_listen_fd_listener() -> Option<std::net::TcpListener> {
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::FromRawFd;
|
||||
#[cfg(target_os = "wasi")]
|
||||
use std::os::wasi::io::FromRawFd;
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
use std::os::fd::FromRawFd;
|
||||
|
||||
let stdlistener = unsafe { std::net::TcpListener::from_raw_fd(3) };
|
||||
stdlistener.set_nonblocking(true).unwrap();
|
||||
|
7
third_party/rust/mio/examples/tcp_server.rs
vendored
7
third_party/rust/mio/examples/tcp_server.rs
vendored
@ -40,7 +40,12 @@ fn main() -> io::Result<()> {
|
||||
println!("You'll see our welcome message and anything you type will be printed here.");
|
||||
|
||||
loop {
|
||||
poll.poll(&mut events, None)?;
|
||||
if let Err(err) = poll.poll(&mut events, None) {
|
||||
if interrupted(&err) {
|
||||
continue;
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
for event in events.iter() {
|
||||
match event.token() {
|
||||
|
7
third_party/rust/mio/examples/udp_server.rs
vendored
7
third_party/rust/mio/examples/udp_server.rs
vendored
@ -40,7 +40,12 @@ fn main() -> io::Result<()> {
|
||||
// Our event loop.
|
||||
loop {
|
||||
// Poll to check if we have events waiting for us.
|
||||
poll.poll(&mut events, None)?;
|
||||
if let Err(err) = poll.poll(&mut events, None) {
|
||||
if err.kind() == io::ErrorKind::Interrupted {
|
||||
continue;
|
||||
}
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
// Process each event.
|
||||
for event in events.iter() {
|
||||
|
4
third_party/rust/mio/src/event/event.rs
vendored
4
third_party/rust/mio/src/event/event.rs
vendored
@ -28,8 +28,8 @@ impl Event {
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// Out-of-band (OOB) data also triggers readable events. But must
|
||||
/// application don't actually read OOB data, this could leave an
|
||||
/// Out-of-band (OOB) data also triggers readable events. But most
|
||||
/// applications don't actually read OOB data, this could leave an
|
||||
/// application open to a Denial-of-Service (Dos) attack, see
|
||||
/// <https://github.com/sandstorm-io/sandstorm-website/blob/58f93346028c0576e8147627667328eaaf4be9fa/_posts/2015-04-08-osx-security-bug.md>.
|
||||
/// However because Mio uses edge-triggers it will not result in an infinite
|
||||
|
11
third_party/rust/mio/src/interest.rs
vendored
11
third_party/rust/mio/src/interest.rs
vendored
@ -38,6 +38,7 @@ impl Interest {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
pub const AIO: Interest = Interest(unsafe { NonZeroU8::new_unchecked(AIO) });
|
||||
@ -63,6 +64,7 @@ impl Interest {
|
||||
/// # silent_dead_code_warning(INTERESTS)
|
||||
/// ```
|
||||
#[allow(clippy::should_implement_trait)]
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub const fn add(self, other: Interest) -> Interest {
|
||||
Interest(unsafe { NonZeroU8::new_unchecked(self.0.get() | other.0.get()) })
|
||||
}
|
||||
@ -87,31 +89,37 @@ impl Interest {
|
||||
/// // Its also possible to remove multiple interests at once.
|
||||
/// assert_eq!(RW_INTERESTS.remove(RW_INTERESTS), None);
|
||||
/// ```
|
||||
#[must_use = "this returns the result of the operation, without modifying the original"]
|
||||
pub fn remove(self, other: Interest) -> Option<Interest> {
|
||||
NonZeroU8::new(self.0.get() & !other.0.get()).map(Interest)
|
||||
}
|
||||
|
||||
/// Returns true if the value includes readable readiness.
|
||||
#[must_use]
|
||||
pub const fn is_readable(self) -> bool {
|
||||
(self.0.get() & READABLE) != 0
|
||||
}
|
||||
|
||||
/// Returns true if the value includes writable readiness.
|
||||
#[must_use]
|
||||
pub const fn is_writable(self) -> bool {
|
||||
(self.0.get() & WRITABLE) != 0
|
||||
}
|
||||
|
||||
/// Returns true if `Interest` contains AIO readiness.
|
||||
#[must_use]
|
||||
pub const fn is_aio(self) -> bool {
|
||||
(self.0.get() & AIO) != 0
|
||||
}
|
||||
|
||||
/// Returns true if `Interest` contains LIO readiness.
|
||||
#[must_use]
|
||||
pub const fn is_lio(self) -> bool {
|
||||
(self.0.get() & LIO) != 0
|
||||
}
|
||||
|
||||
/// Returns true if `Interest` contains priority readiness.
|
||||
#[must_use]
|
||||
pub const fn is_priority(self) -> bool {
|
||||
(self.0.get() & PRIORITY) != 0
|
||||
}
|
||||
@ -156,6 +164,7 @@ impl fmt::Debug for Interest {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
{
|
||||
@ -167,7 +176,7 @@ impl fmt::Debug for Interest {
|
||||
one = true
|
||||
}
|
||||
}
|
||||
#[cfg(any(target_os = "freebsd"))]
|
||||
#[cfg(target_os = "freebsd")]
|
||||
{
|
||||
if self.is_lio() {
|
||||
if one {
|
||||
|
53
third_party/rust/mio/src/io_source.rs
vendored
53
third_party/rust/mio/src/io_source.rs
vendored
@ -1,8 +1,10 @@
|
||||
use std::ops::{Deref, DerefMut};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::AsRawFd;
|
||||
#[cfg(target_os = "wasi")]
|
||||
use std::os::wasi::io::AsRawFd;
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
use std::os::fd::AsRawFd;
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::AsRawFd;
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::AsRawSocket;
|
||||
#[cfg(debug_assertions)]
|
||||
@ -21,7 +23,7 @@ use crate::{event, Interest, Registry, Token};
|
||||
/// Mio supports registering any FD or socket that can be registered with the
|
||||
/// underlying OS selector. `IoSource` provides the necessary bridge.
|
||||
///
|
||||
/// [`RawFd`]: std::os::unix::io::RawFd
|
||||
/// [`RawFd`]: std::os::fd::RawFd
|
||||
/// [`RawSocket`]: std::os::windows::io::RawSocket
|
||||
///
|
||||
/// # Notes
|
||||
@ -32,33 +34,6 @@ use crate::{event, Interest, Registry, Token};
|
||||
///
|
||||
/// [`Poll`]: crate::Poll
|
||||
/// [`do_io`]: IoSource::do_io
|
||||
/*
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// Basic usage.
|
||||
///
|
||||
/// ```
|
||||
/// # use std::error::Error;
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use mio::{Interest, Poll, Token};
|
||||
/// use mio::IoSource;
|
||||
///
|
||||
/// use std::net;
|
||||
///
|
||||
/// let poll = Poll::new()?;
|
||||
///
|
||||
/// // Bind a std TCP listener.
|
||||
/// let listener = net::TcpListener::bind("127.0.0.1:0")?;
|
||||
/// // Wrap it in the `IoSource` type.
|
||||
/// let mut listener = IoSource::new(listener);
|
||||
///
|
||||
/// // Register the listener.
|
||||
/// poll.registry().register(&mut listener, Token(0), Interest::READABLE)?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
*/
|
||||
pub struct IoSource<T> {
|
||||
state: IoSourceState,
|
||||
inner: T,
|
||||
@ -129,7 +104,7 @@ impl<T> DerefMut for IoSource<T> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit"))]
|
||||
impl<T> event::Source for IoSource<T>
|
||||
where
|
||||
T: AsRawFd,
|
||||
@ -142,9 +117,8 @@ where
|
||||
) -> io::Result<()> {
|
||||
#[cfg(debug_assertions)]
|
||||
self.selector_id.associate(registry)?;
|
||||
registry
|
||||
.selector()
|
||||
.register(self.inner.as_raw_fd(), token, interests)
|
||||
self.state
|
||||
.register(registry, token, interests, self.inner.as_raw_fd())
|
||||
}
|
||||
|
||||
fn reregister(
|
||||
@ -155,15 +129,14 @@ where
|
||||
) -> io::Result<()> {
|
||||
#[cfg(debug_assertions)]
|
||||
self.selector_id.check_association(registry)?;
|
||||
registry
|
||||
.selector()
|
||||
.reregister(self.inner.as_raw_fd(), token, interests)
|
||||
self.state
|
||||
.reregister(registry, token, interests, self.inner.as_raw_fd())
|
||||
}
|
||||
|
||||
fn deregister(&mut self, registry: &Registry) -> io::Result<()> {
|
||||
#[cfg(debug_assertions)]
|
||||
self.selector_id.remove_association(registry)?;
|
||||
registry.selector().deregister(self.inner.as_raw_fd())
|
||||
self.state.deregister(registry, self.inner.as_raw_fd())
|
||||
}
|
||||
}
|
||||
|
||||
|
8
third_party/rust/mio/src/lib.rs
vendored
8
third_party/rust/mio/src/lib.rs
vendored
@ -85,6 +85,14 @@ pub mod unix {
|
||||
pub use crate::sys::SourceFd;
|
||||
}
|
||||
|
||||
#[cfg(all(target_os = "hermit", feature = "os-ext"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(target_os = "hermit", feature = "os-ext"))))]
|
||||
pub mod hermit {
|
||||
//! Hermit only extensions.
|
||||
|
||||
pub use crate::sys::SourceFd;
|
||||
}
|
||||
|
||||
#[cfg(all(windows, feature = "os-ext"))]
|
||||
#[cfg_attr(docsrs, doc(cfg(all(windows, feature = "os-ext"))))]
|
||||
pub mod windows {
|
||||
|
4
third_party/rust/mio/src/macros.rs
vendored
4
third_party/rust/mio/src/macros.rs
vendored
@ -51,8 +51,8 @@ macro_rules! cfg_net {
|
||||
macro_rules! cfg_io_source {
|
||||
($($item:item)*) => {
|
||||
$(
|
||||
#[cfg(any(feature = "net", all(unix, feature = "os-ext")))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "net", all(unix, feature = "os-ext")))))]
|
||||
#[cfg(any(feature = "net", all(any(unix, target_os = "hermit"), feature = "os-ext")))]
|
||||
#[cfg_attr(docsrs, doc(cfg(any(feature = "net", all(any(unix, target_os = "hermit"), feature = "os-ext")))))]
|
||||
$item
|
||||
)*
|
||||
}
|
||||
|
2
third_party/rust/mio/src/net/mod.rs
vendored
2
third_party/rust/mio/src/net/mod.rs
vendored
@ -36,4 +36,4 @@ pub use self::udp::UdpSocket;
|
||||
#[cfg(unix)]
|
||||
mod uds;
|
||||
#[cfg(unix)]
|
||||
pub use self::uds::{SocketAddr, UnixDatagram, UnixListener, UnixStream};
|
||||
pub use self::uds::{UnixDatagram, UnixListener, UnixStream};
|
||||
|
66
third_party/rust/mio/src/net/tcp/listener.rs
vendored
66
third_party/rust/mio/src/net/tcp/listener.rs
vendored
@ -1,15 +1,17 @@
|
||||
use std::net::{self, SocketAddr};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(target_os = "wasi")]
|
||||
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::io_source::IoSource;
|
||||
use crate::net::TcpStream;
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit"))]
|
||||
use crate::sys::tcp::set_reuseaddr;
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
use crate::sys::tcp::{bind, listen, new_for_addr};
|
||||
@ -58,7 +60,7 @@ impl TcpListener {
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
|
||||
let socket = new_for_addr(addr)?;
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit"))]
|
||||
let listener = unsafe { TcpListener::from_raw_fd(socket) };
|
||||
#[cfg(windows)]
|
||||
let listener = unsafe { TcpListener::from_raw_socket(socket as _) };
|
||||
@ -166,21 +168,21 @@ impl fmt::Debug for TcpListener {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl IntoRawFd for TcpListener {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl AsRawFd for TcpListener {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl FromRawFd for TcpListener {
|
||||
/// Converts a `RawFd` to a `TcpListener`.
|
||||
///
|
||||
@ -193,6 +195,13 @@ impl FromRawFd for TcpListener {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl AsFd for TcpListener {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl IntoRawSocket for TcpListener {
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
@ -220,29 +229,20 @@ impl FromRawSocket for TcpListener {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl IntoRawFd for TcpListener {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl AsRawFd for TcpListener {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl FromRawFd for TcpListener {
|
||||
/// Converts a `RawFd` to a `TcpListener`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The caller is responsible for ensuring that the socket is in
|
||||
/// non-blocking mode.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> TcpListener {
|
||||
TcpListener::from_std(FromRawFd::from_raw_fd(fd))
|
||||
impl From<TcpListener> for net::TcpListener {
|
||||
fn from(listener: TcpListener) -> Self {
|
||||
// Safety: This is safe since we are extracting the raw fd from a well-constructed
|
||||
// mio::net::TcpListener which ensures that we actually pass in a valid file
|
||||
// descriptor/socket
|
||||
unsafe {
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
{
|
||||
net::TcpListener::from_raw_fd(listener.into_raw_fd())
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
net::TcpListener::from_raw_socket(listener.into_raw_socket())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
77
third_party/rust/mio/src/net/tcp/stream.rs
vendored
77
third_party/rust/mio/src/net/tcp/stream.rs
vendored
@ -1,10 +1,12 @@
|
||||
use std::fmt;
|
||||
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
|
||||
use std::net::{self, Shutdown, SocketAddr};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(target_os = "wasi")]
|
||||
use std::os::wasi::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
|
||||
|
||||
@ -68,12 +70,15 @@ impl TcpStream {
|
||||
/// 1. Call `TcpStream::connect`
|
||||
/// 2. Register the returned stream with at least [write interest].
|
||||
/// 3. Wait for a (writable) event.
|
||||
/// 4. Check `TcpStream::peer_addr`. If it returns `libc::EINPROGRESS` or
|
||||
/// 4. Check `TcpStream::take_error`. If it returns an error, then
|
||||
/// something went wrong. If it returns `Ok(None)`, then proceed to
|
||||
/// step 5.
|
||||
/// 5. Check `TcpStream::peer_addr`. If it returns `libc::EINPROGRESS` or
|
||||
/// `ErrorKind::NotConnected` it means the stream is not yet connected,
|
||||
/// go back to step 3. If it returns an address it means the stream is
|
||||
/// connected, go to step 5. If another error is returned something
|
||||
/// connected, go to step 6. If another error is returned something
|
||||
/// went wrong.
|
||||
/// 5. Now the stream can be used.
|
||||
/// 6. Now the stream can be used.
|
||||
///
|
||||
/// This may return a `WouldBlock` in which case the socket connection
|
||||
/// cannot be completed immediately, it usually means there are insufficient
|
||||
@ -83,7 +88,7 @@ impl TcpStream {
|
||||
#[cfg(not(target_os = "wasi"))]
|
||||
pub fn connect(addr: SocketAddr) -> io::Result<TcpStream> {
|
||||
let socket = new_for_addr(addr)?;
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit"))]
|
||||
let stream = unsafe { TcpStream::from_raw_fd(socket) };
|
||||
#[cfg(windows)]
|
||||
let stream = unsafe { TcpStream::from_raw_socket(socket as _) };
|
||||
@ -227,8 +232,8 @@ impl TcpStream {
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use std::io;
|
||||
/// #[cfg(unix)]
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// #[cfg(any(unix, target_os = "wasi"))]
|
||||
/// use std::os::fd::AsRawFd;
|
||||
/// #[cfg(windows)]
|
||||
/// use std::os::windows::io::AsRawSocket;
|
||||
/// use mio::net::TcpStream;
|
||||
@ -345,21 +350,21 @@ impl fmt::Debug for TcpStream {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl IntoRawFd for TcpStream {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl AsRawFd for TcpStream {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl FromRawFd for TcpStream {
|
||||
/// Converts a `RawFd` to a `TcpStream`.
|
||||
///
|
||||
@ -372,6 +377,13 @@ impl FromRawFd for TcpStream {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl AsFd for TcpStream {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl IntoRawSocket for TcpStream {
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
@ -399,29 +411,20 @@ impl FromRawSocket for TcpStream {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl IntoRawFd for TcpStream {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl AsRawFd for TcpStream {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "wasi")]
|
||||
impl FromRawFd for TcpStream {
|
||||
/// Converts a `RawFd` to a `TcpStream`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// The caller is responsible for ensuring that the socket is in
|
||||
/// non-blocking mode.
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> TcpStream {
|
||||
TcpStream::from_std(FromRawFd::from_raw_fd(fd))
|
||||
impl From<TcpStream> for net::TcpStream {
|
||||
fn from(stream: TcpStream) -> Self {
|
||||
// Safety: This is safe since we are extracting the raw fd from a well-constructed
|
||||
// mio::net::TcpStream which ensures that we actually pass in a valid file
|
||||
// descriptor/socket
|
||||
unsafe {
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
{
|
||||
net::TcpStream::from_raw_fd(stream.into_raw_fd())
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
net::TcpStream::from_raw_socket(stream.into_raw_socket())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
53
third_party/rust/mio/src/net/udp.rs
vendored
53
third_party/rust/mio/src/net/udp.rs
vendored
@ -7,17 +7,19 @@
|
||||
//!
|
||||
//! [portability guidelines]: ../struct.Poll.html#portability
|
||||
|
||||
use crate::io_source::IoSource;
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
use std::fmt;
|
||||
use std::io;
|
||||
use std::net;
|
||||
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(any(unix, target_os = "wasi"))]
|
||||
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::{AsRawSocket, FromRawSocket, IntoRawSocket, RawSocket};
|
||||
use std::{fmt, io, net};
|
||||
|
||||
use crate::io_source::IoSource;
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
/// A User Datagram Protocol socket.
|
||||
///
|
||||
@ -572,8 +574,8 @@ impl UdpSocket {
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use std::io;
|
||||
/// #[cfg(unix)]
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// #[cfg(any(unix, target_os = "wasi"))]
|
||||
/// use std::os::fd::AsRawFd;
|
||||
/// #[cfg(windows)]
|
||||
/// use std::os::windows::io::AsRawSocket;
|
||||
/// use mio::net::UdpSocket;
|
||||
@ -642,21 +644,21 @@ impl fmt::Debug for UdpSocket {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl IntoRawFd for UdpSocket {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl AsRawFd for UdpSocket {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.inner.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl FromRawFd for UdpSocket {
|
||||
/// Converts a `RawFd` to a `UdpSocket`.
|
||||
///
|
||||
@ -669,6 +671,13 @@ impl FromRawFd for UdpSocket {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
impl AsFd for UdpSocket {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl IntoRawSocket for UdpSocket {
|
||||
fn into_raw_socket(self) -> RawSocket {
|
||||
@ -695,3 +704,21 @@ impl FromRawSocket for UdpSocket {
|
||||
UdpSocket::from_std(FromRawSocket::from_raw_socket(socket))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UdpSocket> for net::UdpSocket {
|
||||
fn from(socket: UdpSocket) -> Self {
|
||||
// Safety: This is safe since we are extracting the raw fd from a well-constructed
|
||||
// mio::net::UdpSocket which ensures that we actually pass in a valid file
|
||||
// descriptor/socket
|
||||
unsafe {
|
||||
#[cfg(any(unix, target_os = "hermit", target_os = "wasi"))]
|
||||
{
|
||||
net::UdpSocket::from_raw_fd(socket.into_raw_fd())
|
||||
}
|
||||
#[cfg(windows)]
|
||||
{
|
||||
net::UdpSocket::from_raw_socket(socket.into_raw_socket())
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
48
third_party/rust/mio/src/net/uds/datagram.rs
vendored
48
third_party/rust/mio/src/net/uds/datagram.rs
vendored
@ -1,12 +1,12 @@
|
||||
use crate::io_source::IoSource;
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
use std::net::Shutdown;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::os::unix::net;
|
||||
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::os::unix::net::{self, SocketAddr};
|
||||
use std::path::Path;
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::io_source::IoSource;
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
/// A Unix datagram socket.
|
||||
pub struct UnixDatagram {
|
||||
inner: IoSource<net::UnixDatagram>,
|
||||
@ -15,7 +15,13 @@ pub struct UnixDatagram {
|
||||
impl UnixDatagram {
|
||||
/// Creates a Unix datagram socket bound to the given path.
|
||||
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixDatagram> {
|
||||
sys::uds::datagram::bind(path.as_ref()).map(UnixDatagram::from_std)
|
||||
let addr = SocketAddr::from_pathname(path)?;
|
||||
UnixDatagram::bind_addr(&addr)
|
||||
}
|
||||
|
||||
/// Creates a new `UnixDatagram` bound to the specified socket `address`.
|
||||
pub fn bind_addr(address: &SocketAddr) -> io::Result<UnixDatagram> {
|
||||
sys::uds::datagram::bind_addr(address).map(UnixDatagram::from_std)
|
||||
}
|
||||
|
||||
/// Creates a new `UnixDatagram` from a standard `net::UnixDatagram`.
|
||||
@ -54,24 +60,23 @@ impl UnixDatagram {
|
||||
}
|
||||
|
||||
/// Returns the address of this socket.
|
||||
pub fn local_addr(&self) -> io::Result<sys::SocketAddr> {
|
||||
sys::uds::datagram::local_addr(&self.inner)
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.inner.local_addr()
|
||||
}
|
||||
|
||||
/// Returns the address of this socket's peer.
|
||||
///
|
||||
/// The `connect` method will connect the socket to a peer.
|
||||
pub fn peer_addr(&self) -> io::Result<sys::SocketAddr> {
|
||||
sys::uds::datagram::peer_addr(&self.inner)
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.inner.peer_addr()
|
||||
}
|
||||
|
||||
/// Receives data from the socket.
|
||||
///
|
||||
/// On success, returns the number of bytes read and the address from
|
||||
/// whence the data came.
|
||||
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, sys::SocketAddr)> {
|
||||
self.inner
|
||||
.do_io(|inner| sys::uds::datagram::recv_from(inner, buf))
|
||||
pub fn recv_from(&self, buf: &mut [u8]) -> io::Result<(usize, SocketAddr)> {
|
||||
self.inner.do_io(|inner| inner.recv_from(buf))
|
||||
}
|
||||
|
||||
/// Receives data from the socket.
|
||||
@ -130,7 +135,7 @@ impl UnixDatagram {
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use std::io;
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// use std::os::fd::AsRawFd;
|
||||
/// use mio::net::UnixDatagram;
|
||||
///
|
||||
/// let (dgram1, dgram2) = UnixDatagram::pair()?;
|
||||
@ -234,3 +239,18 @@ impl FromRawFd for UnixDatagram {
|
||||
UnixDatagram::from_std(FromRawFd::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnixDatagram> for net::UnixDatagram {
|
||||
fn from(datagram: UnixDatagram) -> Self {
|
||||
// Safety: This is safe since we are extracting the raw fd from a well-constructed
|
||||
// mio::net::uds::UnixListener which ensures that we actually pass in a valid file
|
||||
// descriptor/socket
|
||||
unsafe { net::UnixDatagram::from_raw_fd(datagram.into_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for UnixDatagram {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
41
third_party/rust/mio/src/net/uds/listener.rs
vendored
41
third_party/rust/mio/src/net/uds/listener.rs
vendored
@ -1,21 +1,27 @@
|
||||
use crate::io_source::IoSource;
|
||||
use crate::net::{SocketAddr, UnixStream};
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::os::unix::net;
|
||||
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::os::unix::net::{self, SocketAddr};
|
||||
use std::path::Path;
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::io_source::IoSource;
|
||||
use crate::net::UnixStream;
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
/// A non-blocking Unix domain socket server.
|
||||
pub struct UnixListener {
|
||||
inner: IoSource<net::UnixListener>,
|
||||
}
|
||||
|
||||
impl UnixListener {
|
||||
/// Creates a new `UnixListener` bound to the specified socket.
|
||||
/// Creates a new `UnixListener` bound to the specified socket `path`.
|
||||
pub fn bind<P: AsRef<Path>>(path: P) -> io::Result<UnixListener> {
|
||||
sys::uds::listener::bind(path.as_ref()).map(UnixListener::from_std)
|
||||
let addr = SocketAddr::from_pathname(path)?;
|
||||
UnixListener::bind_addr(&addr)
|
||||
}
|
||||
|
||||
/// Creates a new `UnixListener` bound to the specified socket `address`.
|
||||
pub fn bind_addr(address: &SocketAddr) -> io::Result<UnixListener> {
|
||||
sys::uds::listener::bind_addr(address).map(UnixListener::from_std)
|
||||
}
|
||||
|
||||
/// Creates a new `UnixListener` from a standard `net::UnixListener`.
|
||||
@ -39,8 +45,8 @@ impl UnixListener {
|
||||
}
|
||||
|
||||
/// Returns the local socket address of this listener.
|
||||
pub fn local_addr(&self) -> io::Result<sys::SocketAddr> {
|
||||
sys::uds::listener::local_addr(&self.inner)
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.inner.local_addr()
|
||||
}
|
||||
|
||||
/// Returns the value of the `SO_ERROR` option.
|
||||
@ -102,3 +108,18 @@ impl FromRawFd for UnixListener {
|
||||
UnixListener::from_std(FromRawFd::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnixListener> for net::UnixListener {
|
||||
fn from(listener: UnixListener) -> Self {
|
||||
// Safety: This is safe since we are extracting the raw fd from a well-constructed
|
||||
// mio::net::uds::UnixListener which ensures that we actually pass in a valid file
|
||||
// descriptor/socket
|
||||
unsafe { net::UnixListener::from_raw_fd(listener.into_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for UnixListener {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
2
third_party/rust/mio/src/net/uds/mod.rs
vendored
2
third_party/rust/mio/src/net/uds/mod.rs
vendored
@ -6,5 +6,3 @@ pub use self::listener::UnixListener;
|
||||
|
||||
mod stream;
|
||||
pub use self::stream::UnixStream;
|
||||
|
||||
pub use crate::sys::SocketAddr;
|
||||
|
46
third_party/rust/mio/src/net/uds/stream.rs
vendored
46
third_party/rust/mio/src/net/uds/stream.rs
vendored
@ -1,13 +1,13 @@
|
||||
use crate::io_source::IoSource;
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
use std::fmt;
|
||||
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
|
||||
use std::net::Shutdown;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::os::unix::net;
|
||||
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::os::unix::net::{self, SocketAddr};
|
||||
use std::path::Path;
|
||||
|
||||
use crate::io_source::IoSource;
|
||||
use crate::{event, sys, Interest, Registry, Token};
|
||||
|
||||
/// A non-blocking Unix stream socket.
|
||||
pub struct UnixStream {
|
||||
inner: IoSource<net::UnixStream>,
|
||||
@ -19,7 +19,16 @@ impl UnixStream {
|
||||
/// This may return a `WouldBlock` in which case the socket connection
|
||||
/// cannot be completed immediately. Usually it means the backlog is full.
|
||||
pub fn connect<P: AsRef<Path>>(path: P) -> io::Result<UnixStream> {
|
||||
sys::uds::stream::connect(path.as_ref()).map(UnixStream::from_std)
|
||||
let addr = SocketAddr::from_pathname(path)?;
|
||||
UnixStream::connect_addr(&addr)
|
||||
}
|
||||
|
||||
/// Connects to the socket named by `address`.
|
||||
///
|
||||
/// This may return a `WouldBlock` in which case the socket connection
|
||||
/// cannot be completed immediately. Usually it means the backlog is full.
|
||||
pub fn connect_addr(address: &SocketAddr) -> io::Result<UnixStream> {
|
||||
sys::uds::stream::connect_addr(address).map(UnixStream::from_std)
|
||||
}
|
||||
|
||||
/// Creates a new `UnixStream` from a standard `net::UnixStream`.
|
||||
@ -50,13 +59,13 @@ impl UnixStream {
|
||||
}
|
||||
|
||||
/// Returns the socket address of the local half of this connection.
|
||||
pub fn local_addr(&self) -> io::Result<sys::SocketAddr> {
|
||||
sys::uds::stream::local_addr(&self.inner)
|
||||
pub fn local_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.inner.local_addr()
|
||||
}
|
||||
|
||||
/// Returns the socket address of the remote half of this connection.
|
||||
pub fn peer_addr(&self) -> io::Result<sys::SocketAddr> {
|
||||
sys::uds::stream::peer_addr(&self.inner)
|
||||
pub fn peer_addr(&self) -> io::Result<SocketAddr> {
|
||||
self.inner.peer_addr()
|
||||
}
|
||||
|
||||
/// Returns the value of the `SO_ERROR` option.
|
||||
@ -91,7 +100,7 @@ impl UnixStream {
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use std::io;
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// use std::os::fd::AsRawFd;
|
||||
/// use mio::net::UnixStream;
|
||||
///
|
||||
/// let (stream1, stream2) = UnixStream::pair()?;
|
||||
@ -243,3 +252,18 @@ impl FromRawFd for UnixStream {
|
||||
UnixStream::from_std(FromRawFd::from_raw_fd(fd))
|
||||
}
|
||||
}
|
||||
|
||||
impl From<UnixStream> for net::UnixStream {
|
||||
fn from(stream: UnixStream) -> Self {
|
||||
// Safety: This is safe since we are extracting the raw fd from a well-constructed
|
||||
// mio::net::uds::UnixStream which ensures that we actually pass in a valid file
|
||||
// descriptor/socket
|
||||
unsafe { net::UnixStream::from_raw_fd(stream.into_raw_fd()) }
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for UnixStream {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
86
third_party/rust/mio/src/poll.rs
vendored
86
third_party/rust/mio/src/poll.rs
vendored
@ -1,9 +1,27 @@
|
||||
use crate::{event, sys, Events, Interest, Token};
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
#[cfg(all(
|
||||
unix,
|
||||
not(mio_unsupported_force_poll_poll),
|
||||
not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "hermit",
|
||||
target_os = "hurd",
|
||||
target_os = "nto",
|
||||
target_os = "solaris",
|
||||
target_os = "vita"
|
||||
)),
|
||||
))]
|
||||
use std::os::fd::{AsRawFd, RawFd};
|
||||
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
|
||||
use std::sync::Arc;
|
||||
use std::time::Duration;
|
||||
use std::{fmt, io};
|
||||
|
||||
use crate::{event, sys, Events, Interest, Token};
|
||||
|
||||
/// Polls for readiness events on all registered values.
|
||||
///
|
||||
/// `Poll` allows a program to monitor a large number of [`event::Source`]s,
|
||||
@ -252,6 +270,9 @@ pub struct Poll {
|
||||
/// Registers I/O resources.
|
||||
pub struct Registry {
|
||||
selector: sys::Selector,
|
||||
/// Whether this selector currently has an associated waker.
|
||||
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
|
||||
has_waker: Arc<AtomicBool>,
|
||||
}
|
||||
|
||||
impl Poll {
|
||||
@ -298,7 +319,11 @@ impl Poll {
|
||||
/// ```
|
||||
pub fn new() -> io::Result<Poll> {
|
||||
sys::Selector::new().map(|selector| Poll {
|
||||
registry: Registry { selector },
|
||||
registry: Registry {
|
||||
selector,
|
||||
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
|
||||
has_waker: Arc::new(AtomicBool::new(false)),
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -411,7 +436,20 @@ impl Poll {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(all(
|
||||
unix,
|
||||
not(mio_unsupported_force_poll_poll),
|
||||
not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "hermit",
|
||||
target_os = "hurd",
|
||||
target_os = "nto",
|
||||
target_os = "solaris",
|
||||
target_os = "vita"
|
||||
)),
|
||||
))]
|
||||
impl AsRawFd for Poll {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.registry.as_raw_fd()
|
||||
@ -668,9 +706,11 @@ impl Registry {
|
||||
/// Event sources registered with this `Registry` will be registered with
|
||||
/// the original `Registry` and `Poll` instance.
|
||||
pub fn try_clone(&self) -> io::Result<Registry> {
|
||||
self.selector
|
||||
.try_clone()
|
||||
.map(|selector| Registry { selector })
|
||||
self.selector.try_clone().map(|selector| Registry {
|
||||
selector,
|
||||
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
|
||||
has_waker: Arc::clone(&self.has_waker),
|
||||
})
|
||||
}
|
||||
|
||||
/// Internal check to ensure only a single `Waker` is active per [`Poll`]
|
||||
@ -678,7 +718,7 @@ impl Registry {
|
||||
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
|
||||
pub(crate) fn register_waker(&self) {
|
||||
assert!(
|
||||
!self.selector.register_waker(),
|
||||
!self.has_waker.swap(true, Ordering::AcqRel),
|
||||
"Only a single `Waker` can be active per `Poll` instance"
|
||||
);
|
||||
}
|
||||
@ -696,7 +736,20 @@ impl fmt::Debug for Registry {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(all(
|
||||
unix,
|
||||
not(mio_unsupported_force_poll_poll),
|
||||
not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "haiku",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hermit",
|
||||
target_os = "hurd",
|
||||
target_os = "nto",
|
||||
target_os = "solaris",
|
||||
target_os = "vita"
|
||||
)),
|
||||
))]
|
||||
impl AsRawFd for Registry {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.selector.as_raw_fd()
|
||||
@ -704,7 +757,18 @@ impl AsRawFd for Registry {
|
||||
}
|
||||
|
||||
cfg_os_poll! {
|
||||
#[cfg(unix)]
|
||||
#[cfg(all(
|
||||
unix,
|
||||
not(mio_unsupported_force_poll_poll),
|
||||
not(any(
|
||||
target_os = "espidf",
|
||||
target_os = "hermit",
|
||||
target_os = "hurd",
|
||||
target_os = "nto",
|
||||
target_os = "solaris",
|
||||
target_os = "vita"
|
||||
)),
|
||||
))]
|
||||
#[test]
|
||||
pub fn as_raw_fd() {
|
||||
let poll = Poll::new().unwrap();
|
||||
|
9
third_party/rust/mio/src/sys/mod.rs
vendored
9
third_party/rust/mio/src/sys/mod.rs
vendored
@ -51,9 +51,10 @@ cfg_os_poll! {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit"))]
|
||||
cfg_os_poll! {
|
||||
mod unix;
|
||||
#[allow(unused_imports)]
|
||||
pub use self::unix::*;
|
||||
}
|
||||
|
||||
@ -76,11 +77,7 @@ cfg_not_os_poll! {
|
||||
#[cfg(unix)]
|
||||
cfg_any_os_ext! {
|
||||
mod unix;
|
||||
#[cfg(feature = "os-ext")]
|
||||
pub use self::unix::SourceFd;
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
cfg_net! {
|
||||
pub use self::unix::SocketAddr;
|
||||
}
|
||||
}
|
||||
|
35
third_party/rust/mio/src/sys/shell/mod.rs
vendored
35
third_party/rust/mio/src/sys/shell/mod.rs
vendored
@ -21,10 +21,16 @@ cfg_net! {
|
||||
|
||||
cfg_io_source! {
|
||||
use std::io;
|
||||
#[cfg(any(unix))]
|
||||
use std::os::fd::RawFd;
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::RawFd;
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::io::RawSocket;
|
||||
|
||||
#[cfg(windows)]
|
||||
#[cfg(any(windows, unix, target_os = "hermit"))]
|
||||
use crate::{Registry, Token, Interest};
|
||||
|
||||
pub(crate) struct IoSourceState;
|
||||
@ -44,6 +50,33 @@ cfg_io_source! {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(unix, target_os = "hermit"))]
|
||||
impl IoSourceState {
|
||||
pub fn register(
|
||||
&mut self,
|
||||
_: &Registry,
|
||||
_: Token,
|
||||
_: Interest,
|
||||
_: RawFd,
|
||||
) -> io::Result<()> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
pub fn reregister(
|
||||
&mut self,
|
||||
_: &Registry,
|
||||
_: Token,
|
||||
_: Interest,
|
||||
_: RawFd,
|
||||
) -> io::Result<()> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
pub fn deregister(&mut self, _: &Registry, _: RawFd) -> io::Result<()> {
|
||||
os_required!()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(windows)]
|
||||
impl IoSourceState {
|
||||
pub fn register(
|
||||
|
@ -1,6 +1,6 @@
|
||||
use std::io;
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::os::fd::{AsRawFd, RawFd};
|
||||
use std::time::Duration;
|
||||
|
||||
pub type Event = usize;
|
||||
@ -18,11 +18,6 @@ impl Selector {
|
||||
pub fn select(&self, _: &mut Events, _: Option<Duration>) -> io::Result<()> {
|
||||
os_required!();
|
||||
}
|
||||
|
||||
#[cfg(all(debug_assertions, not(target_os = "wasi")))]
|
||||
pub fn register_waker(&self) -> bool {
|
||||
os_required!();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
|
2
third_party/rust/mio/src/sys/shell/tcp.rs
vendored
2
third_party/rust/mio/src/sys/shell/tcp.rs
vendored
@ -21,7 +21,7 @@ pub(crate) fn listen(_: &net::TcpListener, _: u32) -> io::Result<()> {
|
||||
os_required!();
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[cfg(any(unix, target_os = "hermit"))]
|
||||
pub(crate) fn set_reuseaddr(_: &net::TcpListener, _: bool) -> io::Result<()> {
|
||||
os_required!();
|
||||
}
|
||||
|
47
third_party/rust/mio/src/sys/shell/uds.rs
vendored
47
third_party/rust/mio/src/sys/shell/uds.rs
vendored
@ -1,10 +1,8 @@
|
||||
pub(crate) mod datagram {
|
||||
use crate::net::SocketAddr;
|
||||
use std::io;
|
||||
use std::os::unix::net;
|
||||
use std::path::Path;
|
||||
use std::os::unix::net::{self, SocketAddr};
|
||||
|
||||
pub(crate) fn bind(_: &Path) -> io::Result<net::UnixDatagram> {
|
||||
pub(crate) fn bind_addr(_: &SocketAddr) -> io::Result<net::UnixDatagram> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
@ -15,61 +13,32 @@ pub(crate) mod datagram {
|
||||
pub(crate) fn pair() -> io::Result<(net::UnixDatagram, net::UnixDatagram)> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
pub(crate) fn local_addr(_: &net::UnixDatagram) -> io::Result<SocketAddr> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
pub(crate) fn peer_addr(_: &net::UnixDatagram) -> io::Result<SocketAddr> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
pub(crate) fn recv_from(
|
||||
_: &net::UnixDatagram,
|
||||
_: &mut [u8],
|
||||
) -> io::Result<(usize, SocketAddr)> {
|
||||
os_required!()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod listener {
|
||||
use crate::net::{SocketAddr, UnixStream};
|
||||
use std::io;
|
||||
use std::os::unix::net;
|
||||
use std::path::Path;
|
||||
use std::os::unix::net::{self, SocketAddr};
|
||||
|
||||
pub(crate) fn bind(_: &Path) -> io::Result<net::UnixListener> {
|
||||
use crate::net::UnixStream;
|
||||
|
||||
pub(crate) fn bind_addr(_: &SocketAddr) -> io::Result<net::UnixListener> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
pub(crate) fn accept(_: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
pub(crate) fn local_addr(_: &net::UnixListener) -> io::Result<SocketAddr> {
|
||||
os_required!()
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod stream {
|
||||
use crate::net::SocketAddr;
|
||||
use std::io;
|
||||
use std::os::unix::net;
|
||||
use std::path::Path;
|
||||
use std::os::unix::net::{self, SocketAddr};
|
||||
|
||||
pub(crate) fn connect(_: &Path) -> io::Result<net::UnixStream> {
|
||||
pub(crate) fn connect_addr(_: &SocketAddr) -> io::Result<net::UnixStream> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
pub(crate) fn pair() -> io::Result<(net::UnixStream, net::UnixStream)> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
pub(crate) fn local_addr(_: &net::UnixStream) -> io::Result<SocketAddr> {
|
||||
os_required!()
|
||||
}
|
||||
|
||||
pub(crate) fn peer_addr(_: &net::UnixStream) -> io::Result<SocketAddr> {
|
||||
os_required!()
|
||||
}
|
||||
}
|
||||
|
163
third_party/rust/mio/src/sys/unix/mod.rs
vendored
163
third_party/rust/mio/src/sys/unix/mod.rs
vendored
@ -4,8 +4,9 @@
|
||||
#[allow(unused_macros)]
|
||||
macro_rules! syscall {
|
||||
($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
|
||||
#[allow(unused_unsafe)]
|
||||
let res = unsafe { libc::$fn($($arg, )*) };
|
||||
if res == -1 {
|
||||
if res < 0 {
|
||||
Err(std::io::Error::last_os_error())
|
||||
} else {
|
||||
Ok(res)
|
||||
@ -14,59 +15,149 @@ macro_rules! syscall {
|
||||
}
|
||||
|
||||
cfg_os_poll! {
|
||||
#[cfg_attr(all(
|
||||
not(mio_unsupported_force_poll_poll),
|
||||
any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "redox",
|
||||
)
|
||||
), path = "selector/epoll.rs")]
|
||||
#[cfg_attr(all(
|
||||
not(mio_unsupported_force_poll_poll),
|
||||
any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
)
|
||||
), path = "selector/kqueue.rs")]
|
||||
#[cfg_attr(any(
|
||||
mio_unsupported_force_poll_poll,
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "haiku",
|
||||
target_os = "hermit",
|
||||
target_os = "hurd",
|
||||
target_os = "nto",
|
||||
target_os = "solaris",
|
||||
target_os = "vita",
|
||||
), path = "selector/poll.rs")]
|
||||
mod selector;
|
||||
pub(crate) use self::selector::{event, Event, Events, Selector};
|
||||
pub(crate) use self::selector::*;
|
||||
|
||||
#[cfg_attr(all(
|
||||
not(mio_unsupported_force_waker_pipe),
|
||||
any(
|
||||
target_os = "android",
|
||||
target_os = "espidf",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hermit",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
)
|
||||
), path = "waker/eventfd.rs")]
|
||||
#[cfg_attr(all(
|
||||
not(mio_unsupported_force_waker_pipe),
|
||||
not(mio_unsupported_force_poll_poll), // `kqueue(2)` based waker doesn't work with `poll(2)`.
|
||||
any(
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
)
|
||||
), path = "waker/kqueue.rs")]
|
||||
#[cfg_attr(any(
|
||||
// NOTE: also add to the list list for the `pipe` module below.
|
||||
mio_unsupported_force_waker_pipe,
|
||||
all(
|
||||
// `kqueue(2)` based waker doesn't work with `poll(2)`.
|
||||
mio_unsupported_force_poll_poll,
|
||||
any(
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
),
|
||||
),
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "netbsd",
|
||||
target_os = "nto",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "vita",
|
||||
), path = "waker/pipe.rs")]
|
||||
mod waker;
|
||||
// NOTE: the `Waker` type is expected in the selector module as the
|
||||
// `poll(2)` implementation needs to do some special stuff.
|
||||
|
||||
mod sourcefd;
|
||||
#[cfg(feature = "os-ext")]
|
||||
pub use self::sourcefd::SourceFd;
|
||||
|
||||
mod waker;
|
||||
pub(crate) use self::waker::Waker;
|
||||
|
||||
cfg_net! {
|
||||
mod net;
|
||||
|
||||
pub(crate) mod tcp;
|
||||
pub(crate) mod udp;
|
||||
#[cfg(not(target_os = "hermit"))]
|
||||
pub(crate) mod uds;
|
||||
pub use self::uds::SocketAddr;
|
||||
}
|
||||
|
||||
cfg_io_source! {
|
||||
use std::io;
|
||||
|
||||
// Both `kqueue` and `epoll` don't need to hold any user space state.
|
||||
pub(crate) struct IoSourceState;
|
||||
|
||||
impl IoSourceState {
|
||||
pub fn new() -> IoSourceState {
|
||||
IoSourceState
|
||||
}
|
||||
|
||||
pub fn do_io<T, F, R>(&self, f: F, io: &T) -> io::Result<R>
|
||||
where
|
||||
F: FnOnce(&T) -> io::Result<R>,
|
||||
{
|
||||
// We don't hold state, so we can just call the function and
|
||||
// return.
|
||||
f(io)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_os_ext! {
|
||||
pub(crate) mod pipe;
|
||||
}
|
||||
#[cfg(all(
|
||||
any(
|
||||
// For the public `pipe` module, must match `cfg_os_ext` macro.
|
||||
feature = "os-ext",
|
||||
// For the `Waker` type based on a pipe.
|
||||
mio_unsupported_force_waker_pipe,
|
||||
all(
|
||||
// `kqueue(2)` based waker doesn't work with `poll(2)`.
|
||||
mio_unsupported_force_poll_poll,
|
||||
any(
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
),
|
||||
),
|
||||
// NOTE: also add to the list list for the `pipe` module below.
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "netbsd",
|
||||
target_os = "nto",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "vita",
|
||||
),
|
||||
// Hermit doesn't support pipes.
|
||||
not(target_os = "hermit"),
|
||||
))]
|
||||
pub(crate) mod pipe;
|
||||
}
|
||||
|
||||
cfg_not_os_poll! {
|
||||
cfg_net! {
|
||||
mod uds;
|
||||
pub use self::uds::SocketAddr;
|
||||
}
|
||||
|
||||
cfg_any_os_ext! {
|
||||
mod sourcefd;
|
||||
#[cfg(feature = "os-ext")]
|
||||
pub use self::sourcefd::SourceFd;
|
||||
}
|
||||
}
|
||||
|
39
third_party/rust/mio/src/sys/unix/net.rs
vendored
39
third_party/rust/mio/src/sys/unix/net.rs
vendored
@ -17,12 +17,17 @@ pub(crate) fn new_socket(domain: libc::c_int, socket_type: libc::c_int) -> io::R
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "hurd",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
target_os = "hermit",
|
||||
))]
|
||||
let socket_type = socket_type | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
|
||||
#[cfg(target_os = "nto")]
|
||||
let socket_type = socket_type | libc::SOCK_CLOEXEC;
|
||||
|
||||
let socket = syscall!(socket(domain, socket_type, 0))?;
|
||||
|
||||
@ -31,6 +36,7 @@ pub(crate) fn new_socket(domain: libc::c_int, socket_type: libc::c_int) -> io::R
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
if let Err(err) = syscall!(setsockopt(
|
||||
@ -44,18 +50,23 @@ pub(crate) fn new_socket(domain: libc::c_int, socket_type: libc::c_int) -> io::R
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
// Darwin doesn't have SOCK_NONBLOCK or SOCK_CLOEXEC.
|
||||
// Darwin (and others) doesn't have SOCK_NONBLOCK or SOCK_CLOEXEC.
|
||||
#[cfg(any(
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "nto",
|
||||
))]
|
||||
{
|
||||
if let Err(err) = syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK)) {
|
||||
let _ = syscall!(close(socket));
|
||||
return Err(err);
|
||||
}
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "vita", target_os = "nto")))]
|
||||
if let Err(err) = syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC)) {
|
||||
let _ = syscall!(close(socket));
|
||||
return Err(err);
|
||||
@ -95,18 +106,33 @@ pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_
|
||||
sin_family: libc::AF_INET as libc::sa_family_t,
|
||||
sin_port: addr.port().to_be(),
|
||||
sin_addr,
|
||||
#[cfg(not(any(target_os = "haiku", target_os = "vita")))]
|
||||
sin_zero: [0; 8],
|
||||
#[cfg(target_os = "haiku")]
|
||||
sin_zero: [0; 24],
|
||||
#[cfg(target_os = "vita")]
|
||||
sin_zero: [0; 6],
|
||||
#[cfg(any(
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "hermit",
|
||||
target_os = "nto",
|
||||
))]
|
||||
sin_len: 0,
|
||||
#[cfg(target_os = "vita")]
|
||||
sin_vport: addr.port().to_be(),
|
||||
};
|
||||
|
||||
let sockaddr = SocketAddrCRepr { v4: sockaddr_in };
|
||||
@ -123,17 +149,26 @@ pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_
|
||||
sin6_flowinfo: addr.flowinfo(),
|
||||
sin6_scope_id: addr.scope_id(),
|
||||
#[cfg(any(
|
||||
target_os = "aix",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "haiku",
|
||||
target_os = "hurd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "nto",
|
||||
))]
|
||||
sin6_len: 0,
|
||||
#[cfg(target_os = "illumos")]
|
||||
#[cfg(target_os = "vita")]
|
||||
sin6_vport: addr.port().to_be(),
|
||||
#[cfg(any(target_os = "illumos", target_os = "solaris"))]
|
||||
__sin6_src_id: 0,
|
||||
};
|
||||
|
||||
|
166
third_party/rust/mio/src/sys/unix/pipe.rs
vendored
166
third_party/rust/mio/src/sys/unix/pipe.rs
vendored
@ -2,9 +2,70 @@
|
||||
//!
|
||||
//! See the [`new`] function for documentation.
|
||||
|
||||
use std::io;
|
||||
use std::os::fd::RawFd;
|
||||
|
||||
pub(crate) fn new_raw() -> io::Result<[RawFd; 2]> {
|
||||
let mut fds: [RawFd; 2] = [-1, -1];
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "illumos",
|
||||
target_os = "redox",
|
||||
target_os = "solaris",
|
||||
target_os = "vita",
|
||||
))]
|
||||
unsafe {
|
||||
if libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC | libc::O_NONBLOCK) != 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
target_os = "espidf",
|
||||
target_os = "nto",
|
||||
))]
|
||||
unsafe {
|
||||
// For platforms that don't have `pipe2(2)` we need to manually set the
|
||||
// correct flags on the file descriptor.
|
||||
if libc::pipe(fds.as_mut_ptr()) != 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
for fd in &fds {
|
||||
if libc::fcntl(*fd, libc::F_SETFL, libc::O_NONBLOCK) != 0
|
||||
|| libc::fcntl(*fd, libc::F_SETFD, libc::FD_CLOEXEC) != 0
|
||||
{
|
||||
let err = io::Error::last_os_error();
|
||||
// Don't leak file descriptors. Can't handle closing error though.
|
||||
let _ = libc::close(fds[0]);
|
||||
let _ = libc::close(fds[1]);
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(fds)
|
||||
}
|
||||
|
||||
cfg_os_ext! {
|
||||
use std::fs::File;
|
||||
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
|
||||
use std::io::{IoSlice, IoSliceMut, Read, Write};
|
||||
use std::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd};
|
||||
use std::process::{ChildStderr, ChildStdin, ChildStdout};
|
||||
|
||||
use crate::io_source::IoSource;
|
||||
@ -145,70 +206,10 @@ use crate::{event, Interest, Registry, Token};
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn new() -> io::Result<(Sender, Receiver)> {
|
||||
let mut fds: [RawFd; 2] = [-1, -1];
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "illumos",
|
||||
target_os = "redox",
|
||||
))]
|
||||
unsafe {
|
||||
if libc::pipe2(fds.as_mut_ptr(), libc::O_CLOEXEC | libc::O_NONBLOCK) != 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
unsafe {
|
||||
// For platforms that don't have `pipe2(2)` we need to manually set the
|
||||
// correct flags on the file descriptor.
|
||||
if libc::pipe(fds.as_mut_ptr()) != 0 {
|
||||
return Err(io::Error::last_os_error());
|
||||
}
|
||||
|
||||
for fd in &fds {
|
||||
if libc::fcntl(*fd, libc::F_SETFL, libc::O_NONBLOCK) != 0
|
||||
|| libc::fcntl(*fd, libc::F_SETFD, libc::FD_CLOEXEC) != 0
|
||||
{
|
||||
let err = io::Error::last_os_error();
|
||||
// Don't leak file descriptors. Can't handle closing error though.
|
||||
let _ = libc::close(fds[0]);
|
||||
let _ = libc::close(fds[1]);
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "android",
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "illumos",
|
||||
target_os = "ios",
|
||||
target_os = "linux",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
)))]
|
||||
compile_error!("unsupported target for `mio::unix::pipe`");
|
||||
|
||||
// SAFETY: we just initialised the `fds` above.
|
||||
let fds = new_raw()?;
|
||||
// SAFETY: `new_raw` initialised the `fds` above.
|
||||
let r = unsafe { Receiver::from_raw_fd(fds[0]) };
|
||||
let w = unsafe { Sender::from_raw_fd(fds[1]) };
|
||||
|
||||
Ok((w, r))
|
||||
}
|
||||
|
||||
@ -244,7 +245,7 @@ impl Sender {
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use std::io;
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// use std::os::fd::AsRawFd;
|
||||
/// use mio::unix::pipe;
|
||||
///
|
||||
/// let (sender, receiver) = pipe::new()?;
|
||||
@ -377,6 +378,12 @@ impl IntoRawFd for Sender {
|
||||
}
|
||||
}
|
||||
|
||||
impl AsFd for Sender {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
/// Receiving end of an Unix pipe.
|
||||
///
|
||||
/// See [`new`] for documentation, including examples.
|
||||
@ -409,7 +416,7 @@ impl Receiver {
|
||||
/// #
|
||||
/// # fn main() -> Result<(), Box<dyn Error>> {
|
||||
/// use std::io;
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// use std::os::fd::AsRawFd;
|
||||
/// use mio::unix::pipe;
|
||||
///
|
||||
/// let (sender, receiver) = pipe::new()?;
|
||||
@ -524,11 +531,9 @@ impl From<ChildStderr> for Receiver {
|
||||
}
|
||||
}
|
||||
|
||||
impl FromRawFd for Receiver {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Receiver {
|
||||
Receiver {
|
||||
inner: IoSource::new(File::from_raw_fd(fd)),
|
||||
}
|
||||
impl IntoRawFd for Receiver {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -538,13 +543,21 @@ impl AsRawFd for Receiver {
|
||||
}
|
||||
}
|
||||
|
||||
impl IntoRawFd for Receiver {
|
||||
fn into_raw_fd(self) -> RawFd {
|
||||
self.inner.into_inner().into_raw_fd()
|
||||
impl FromRawFd for Receiver {
|
||||
unsafe fn from_raw_fd(fd: RawFd) -> Receiver {
|
||||
Receiver {
|
||||
inner: IoSource::new(File::from_raw_fd(fd)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "illumos"))]
|
||||
impl AsFd for Receiver {
|
||||
fn as_fd(&self) -> BorrowedFd<'_> {
|
||||
self.inner.as_fd()
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(any(target_os = "illumos", target_os = "solaris", target_os = "vita")))]
|
||||
fn set_nonblocking(fd: RawFd, nonblocking: bool) -> io::Result<()> {
|
||||
let value = nonblocking as libc::c_int;
|
||||
if unsafe { libc::ioctl(fd, libc::FIONBIO, &value) } == -1 {
|
||||
@ -554,7 +567,7 @@ fn set_nonblocking(fd: RawFd, nonblocking: bool) -> io::Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "illumos")]
|
||||
#[cfg(any(target_os = "illumos", target_os = "solaris", target_os = "vita"))]
|
||||
fn set_nonblocking(fd: RawFd, nonblocking: bool) -> io::Result<()> {
|
||||
let flags = unsafe { libc::fcntl(fd, libc::F_GETFL) };
|
||||
if flags < 0 {
|
||||
@ -575,3 +588,4 @@ fn set_nonblocking(fd: RawFd, nonblocking: bool) -> io::Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
} // `cfg_os_ext!`.
|
||||
|
112
third_party/rust/mio/src/sys/unix/selector/epoll.rs
vendored
112
third_party/rust/mio/src/sys/unix/selector/epoll.rs
vendored
@ -1,11 +1,12 @@
|
||||
use crate::{Interest, Token};
|
||||
use std::os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd};
|
||||
#[cfg(debug_assertions)]
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::time::Duration;
|
||||
use std::{io, ptr};
|
||||
|
||||
use libc::{EPOLLET, EPOLLIN, EPOLLOUT, EPOLLPRI, EPOLLRDHUP};
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
#[cfg(debug_assertions)]
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::time::Duration;
|
||||
use std::{cmp, i32, io, ptr};
|
||||
|
||||
use crate::{Interest, Token};
|
||||
|
||||
/// Unique id for use as `SelectorId`.
|
||||
#[cfg(debug_assertions)]
|
||||
@ -15,93 +16,45 @@ static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
|
||||
pub struct Selector {
|
||||
#[cfg(debug_assertions)]
|
||||
id: usize,
|
||||
ep: RawFd,
|
||||
#[cfg(debug_assertions)]
|
||||
has_waker: AtomicBool,
|
||||
ep: OwnedFd,
|
||||
}
|
||||
|
||||
impl Selector {
|
||||
pub fn new() -> io::Result<Selector> {
|
||||
#[cfg(not(target_os = "android"))]
|
||||
let res = syscall!(epoll_create1(libc::EPOLL_CLOEXEC));
|
||||
|
||||
// On Android < API level 16 `epoll_create1` is not defined, so use a
|
||||
// raw system call.
|
||||
// According to libuv, `EPOLL_CLOEXEC` is not defined on Android API <
|
||||
// 21. But `EPOLL_CLOEXEC` is an alias for `O_CLOEXEC` on that platform,
|
||||
// so we use it instead.
|
||||
#[cfg(target_os = "android")]
|
||||
let res = syscall!(syscall(libc::SYS_epoll_create1, libc::O_CLOEXEC));
|
||||
|
||||
let ep = match res {
|
||||
Ok(ep) => ep as RawFd,
|
||||
Err(err) => {
|
||||
// When `epoll_create1` is not available fall back to use
|
||||
// `epoll_create` followed by `fcntl`.
|
||||
if let Some(libc::ENOSYS) = err.raw_os_error() {
|
||||
match syscall!(epoll_create(1024)) {
|
||||
Ok(ep) => match syscall!(fcntl(ep, libc::F_SETFD, libc::FD_CLOEXEC)) {
|
||||
Ok(ep) => ep as RawFd,
|
||||
Err(err) => {
|
||||
// `fcntl` failed, cleanup `ep`.
|
||||
let _ = unsafe { libc::close(ep) };
|
||||
return Err(err);
|
||||
}
|
||||
},
|
||||
Err(err) => return Err(err),
|
||||
}
|
||||
} else {
|
||||
return Err(err);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// SAFETY: `epoll_create1(2)` ensures the fd is valid.
|
||||
let ep = unsafe { OwnedFd::from_raw_fd(syscall!(epoll_create1(libc::EPOLL_CLOEXEC))?) };
|
||||
Ok(Selector {
|
||||
#[cfg(debug_assertions)]
|
||||
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
|
||||
ep,
|
||||
#[cfg(debug_assertions)]
|
||||
has_waker: AtomicBool::new(false),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_clone(&self) -> io::Result<Selector> {
|
||||
syscall!(fcntl(self.ep, libc::F_DUPFD_CLOEXEC, super::LOWEST_FD)).map(|ep| Selector {
|
||||
self.ep.try_clone().map(|ep| Selector {
|
||||
// It's the same selector, so we use the same id.
|
||||
#[cfg(debug_assertions)]
|
||||
id: self.id,
|
||||
ep,
|
||||
#[cfg(debug_assertions)]
|
||||
has_waker: AtomicBool::new(self.has_waker.load(Ordering::Acquire)),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn select(&self, events: &mut Events, timeout: Option<Duration>) -> io::Result<()> {
|
||||
// A bug in kernels < 2.6.37 makes timeouts larger than LONG_MAX / CONFIG_HZ
|
||||
// (approx. 30 minutes with CONFIG_HZ=1200) effectively infinite on 32 bits
|
||||
// architectures. The magic number is the same constant used by libuv.
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const MAX_SAFE_TIMEOUT: u128 = 1789569;
|
||||
#[cfg(not(target_pointer_width = "32"))]
|
||||
const MAX_SAFE_TIMEOUT: u128 = libc::c_int::max_value() as u128;
|
||||
|
||||
let timeout = timeout
|
||||
.map(|to| {
|
||||
// `Duration::as_millis` truncates, so round up. This avoids
|
||||
// turning sub-millisecond timeouts into a zero timeout, unless
|
||||
// the caller explicitly requests that by specifying a zero
|
||||
// timeout.
|
||||
let to_ms = to
|
||||
.checked_add(Duration::from_nanos(999_999))
|
||||
to.checked_add(Duration::from_nanos(999_999))
|
||||
.unwrap_or(to)
|
||||
.as_millis();
|
||||
cmp::min(MAX_SAFE_TIMEOUT, to_ms) as libc::c_int
|
||||
.as_millis() as libc::c_int
|
||||
})
|
||||
.unwrap_or(-1);
|
||||
|
||||
events.clear();
|
||||
syscall!(epoll_wait(
|
||||
self.ep,
|
||||
self.ep.as_raw_fd(),
|
||||
events.as_mut_ptr(),
|
||||
events.capacity() as i32,
|
||||
timeout,
|
||||
@ -121,7 +74,8 @@ impl Selector {
|
||||
_pad: 0,
|
||||
};
|
||||
|
||||
syscall!(epoll_ctl(self.ep, libc::EPOLL_CTL_ADD, fd, &mut event)).map(|_| ())
|
||||
let ep = self.ep.as_raw_fd();
|
||||
syscall!(epoll_ctl(ep, libc::EPOLL_CTL_ADD, fd, &mut event)).map(|_| ())
|
||||
}
|
||||
|
||||
pub fn reregister(&self, fd: RawFd, token: Token, interests: Interest) -> io::Result<()> {
|
||||
@ -132,16 +86,13 @@ impl Selector {
|
||||
_pad: 0,
|
||||
};
|
||||
|
||||
syscall!(epoll_ctl(self.ep, libc::EPOLL_CTL_MOD, fd, &mut event)).map(|_| ())
|
||||
let ep = self.ep.as_raw_fd();
|
||||
syscall!(epoll_ctl(ep, libc::EPOLL_CTL_MOD, fd, &mut event)).map(|_| ())
|
||||
}
|
||||
|
||||
pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
|
||||
syscall!(epoll_ctl(self.ep, libc::EPOLL_CTL_DEL, fd, ptr::null_mut())).map(|_| ())
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub fn register_waker(&self) -> bool {
|
||||
self.has_waker.swap(true, Ordering::AcqRel)
|
||||
let ep = self.ep.as_raw_fd();
|
||||
syscall!(epoll_ctl(ep, libc::EPOLL_CTL_DEL, fd, ptr::null_mut())).map(|_| ())
|
||||
}
|
||||
}
|
||||
|
||||
@ -156,15 +107,7 @@ cfg_io_source! {
|
||||
|
||||
impl AsRawFd for Selector {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.ep
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Selector {
|
||||
fn drop(&mut self) {
|
||||
if let Err(err) = syscall!(close(self.ep)) {
|
||||
error!("error closing epoll: {}", err);
|
||||
}
|
||||
self.ep.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -265,9 +208,7 @@ pub mod event {
|
||||
libc::EPOLLET,
|
||||
libc::EPOLLRDHUP,
|
||||
libc::EPOLLONESHOT,
|
||||
#[cfg(target_os = "linux")]
|
||||
libc::EPOLLEXCLUSIVE,
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
libc::EPOLLWAKEUP,
|
||||
libc::EPOLL_CLOEXEC,
|
||||
);
|
||||
@ -281,9 +222,10 @@ pub mod event {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "android")]
|
||||
#[test]
|
||||
fn assert_close_on_exec_flag() {
|
||||
// This assertion need to be true for Selector::new.
|
||||
assert_eq!(libc::O_CLOEXEC, libc::EPOLL_CLOEXEC);
|
||||
// No special requirement from the implementation around waking.
|
||||
pub(crate) use crate::sys::unix::waker::Waker;
|
||||
|
||||
cfg_io_source! {
|
||||
mod stateless_io_source;
|
||||
pub(crate) use stateless_io_source::IoSourceState;
|
||||
}
|
||||
|
108
third_party/rust/mio/src/sys/unix/selector/kqueue.rs
vendored
108
third_party/rust/mio/src/sys/unix/selector/kqueue.rs
vendored
@ -1,9 +1,9 @@
|
||||
use crate::{Interest, Token};
|
||||
use std::mem::{self, MaybeUninit};
|
||||
use std::ops::{Deref, DerefMut};
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::os::fd::{AsRawFd, FromRawFd, OwnedFd, RawFd};
|
||||
#[cfg(debug_assertions)]
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
||||
use std::time::Duration;
|
||||
use std::{cmp, io, ptr, slice};
|
||||
|
||||
@ -24,6 +24,7 @@ type Filter = libc::c_short;
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
type Filter = i16;
|
||||
@ -37,6 +38,7 @@ type Flags = libc::c_ushort;
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
type Flags = u16;
|
||||
@ -65,40 +67,33 @@ macro_rules! kevent {
|
||||
pub struct Selector {
|
||||
#[cfg(debug_assertions)]
|
||||
id: usize,
|
||||
kq: RawFd,
|
||||
#[cfg(debug_assertions)]
|
||||
has_waker: AtomicBool,
|
||||
kq: OwnedFd,
|
||||
}
|
||||
|
||||
impl Selector {
|
||||
pub fn new() -> io::Result<Selector> {
|
||||
let kq = syscall!(kqueue())?;
|
||||
let selector = Selector {
|
||||
// SAFETY: `kqueue(2)` ensures the fd is valid.
|
||||
let kq = unsafe { OwnedFd::from_raw_fd(syscall!(kqueue())?) };
|
||||
syscall!(fcntl(kq.as_raw_fd(), libc::F_SETFD, libc::FD_CLOEXEC))?;
|
||||
Ok(Selector {
|
||||
#[cfg(debug_assertions)]
|
||||
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
|
||||
kq,
|
||||
#[cfg(debug_assertions)]
|
||||
has_waker: AtomicBool::new(false),
|
||||
};
|
||||
|
||||
syscall!(fcntl(kq, libc::F_SETFD, libc::FD_CLOEXEC))?;
|
||||
Ok(selector)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_clone(&self) -> io::Result<Selector> {
|
||||
syscall!(fcntl(self.kq, libc::F_DUPFD_CLOEXEC, super::LOWEST_FD)).map(|kq| Selector {
|
||||
self.kq.try_clone().map(|kq| Selector {
|
||||
// It's the same selector, so we use the same id.
|
||||
#[cfg(debug_assertions)]
|
||||
id: self.id,
|
||||
kq,
|
||||
#[cfg(debug_assertions)]
|
||||
has_waker: AtomicBool::new(self.has_waker.load(Ordering::Acquire)),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn select(&self, events: &mut Events, timeout: Option<Duration>) -> io::Result<()> {
|
||||
let timeout = timeout.map(|to| libc::timespec {
|
||||
tv_sec: cmp::min(to.as_secs(), libc::time_t::max_value() as u64) as libc::time_t,
|
||||
tv_sec: cmp::min(to.as_secs(), libc::time_t::MAX as u64) as libc::time_t,
|
||||
// `Duration::subsec_nanos` is guaranteed to be less than one
|
||||
// billion (the number of nanoseconds in a second), making the
|
||||
// cast to i32 safe. The cast itself is needed for platforms
|
||||
@ -112,7 +107,7 @@ impl Selector {
|
||||
|
||||
events.clear();
|
||||
syscall!(kevent(
|
||||
self.kq,
|
||||
self.kq.as_raw_fd(),
|
||||
ptr::null(),
|
||||
0,
|
||||
events.as_mut_ptr(),
|
||||
@ -162,7 +157,7 @@ impl Selector {
|
||||
// the array.
|
||||
slice::from_raw_parts_mut(changes[0].as_mut_ptr(), n_changes)
|
||||
};
|
||||
kevent_register(self.kq, changes, &[libc::EPIPE as i64])
|
||||
kevent_register(self.kq.as_raw_fd(), changes, &[libc::EPIPE as i64])
|
||||
}
|
||||
|
||||
pub fn reregister(&self, fd: RawFd, token: Token, interests: Interest) -> io::Result<()> {
|
||||
@ -192,7 +187,7 @@ impl Selector {
|
||||
//
|
||||
// For the explanation of ignoring `EPIPE` see `register`.
|
||||
kevent_register(
|
||||
self.kq,
|
||||
self.kq.as_raw_fd(),
|
||||
&mut changes,
|
||||
&[libc::ENOENT as i64, libc::EPIPE as i64],
|
||||
)
|
||||
@ -210,12 +205,7 @@ impl Selector {
|
||||
// the ENOENT error when it comes up. The ENOENT error informs us that
|
||||
// the filter wasn't there in first place, but we don't really care
|
||||
// about that since our goal is to remove it.
|
||||
kevent_register(self.kq, &mut changes, &[libc::ENOENT as i64])
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub fn register_waker(&self) -> bool {
|
||||
self.has_waker.swap(true, Ordering::AcqRel)
|
||||
kevent_register(self.kq.as_raw_fd(), &mut changes, &[libc::ENOENT as i64])
|
||||
}
|
||||
|
||||
// Used by `Waker`.
|
||||
@ -224,6 +214,7 @@ impl Selector {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
pub fn setup_waker(&self, token: Token) -> io::Result<()> {
|
||||
@ -235,7 +226,8 @@ impl Selector {
|
||||
token.0
|
||||
);
|
||||
|
||||
syscall!(kevent(self.kq, &kevent, 1, &mut kevent, 1, ptr::null())).and_then(|_| {
|
||||
let kq = self.kq.as_raw_fd();
|
||||
syscall!(kevent(kq, &kevent, 1, &mut kevent, 1, ptr::null())).and_then(|_| {
|
||||
if (kevent.flags & libc::EV_ERROR) != 0 && kevent.data != 0 {
|
||||
Err(io::Error::from_raw_os_error(kevent.data as i32))
|
||||
} else {
|
||||
@ -250,6 +242,7 @@ impl Selector {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
pub fn wake(&self, token: Token) -> io::Result<()> {
|
||||
@ -261,7 +254,8 @@ impl Selector {
|
||||
);
|
||||
kevent.fflags = libc::NOTE_TRIGGER;
|
||||
|
||||
syscall!(kevent(self.kq, &kevent, 1, &mut kevent, 1, ptr::null())).and_then(|_| {
|
||||
let kq = self.kq.as_raw_fd();
|
||||
syscall!(kevent(kq, &kevent, 1, &mut kevent, 1, ptr::null())).and_then(|_| {
|
||||
if (kevent.flags & libc::EV_ERROR) != 0 && kevent.data != 0 {
|
||||
Err(io::Error::from_raw_os_error(kevent.data as i32))
|
||||
} else {
|
||||
@ -325,15 +319,7 @@ cfg_io_source! {
|
||||
|
||||
impl AsRawFd for Selector {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.kq
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for Selector {
|
||||
fn drop(&mut self) {
|
||||
if let Err(err) = syscall!(close(self.kq)) {
|
||||
error!("error closing kqueue: {}", err);
|
||||
}
|
||||
self.kq.as_raw_fd()
|
||||
}
|
||||
}
|
||||
|
||||
@ -387,6 +373,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
// Used by the `Awakener`. On platforms that use `eventfd` or a unix
|
||||
@ -400,6 +387,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
)))]
|
||||
{
|
||||
@ -440,6 +428,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
{
|
||||
@ -451,6 +440,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
)))]
|
||||
{
|
||||
@ -489,6 +479,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
libc::EVFILT_FS,
|
||||
@ -500,6 +491,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
libc::EVFILT_USER,
|
||||
@ -513,6 +505,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::EVFILT_MACHPORT,
|
||||
@ -520,6 +513,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::EVFILT_VM,
|
||||
@ -545,11 +539,14 @@ pub mod event {
|
||||
libc::EV_FLAG1,
|
||||
libc::EV_ERROR,
|
||||
libc::EV_EOF,
|
||||
// Not stable across OS versions on OpenBSD.
|
||||
#[cfg(not(target_os = "openbsd"))]
|
||||
libc::EV_SYSFLAGS,
|
||||
#[cfg(any(
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::EV_FLAG0,
|
||||
@ -557,6 +554,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::EV_POLL,
|
||||
@ -564,6 +562,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::EV_OOBAND,
|
||||
@ -584,6 +583,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
libc::NOTE_TRIGGER,
|
||||
@ -593,6 +593,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
libc::NOTE_FFNOP,
|
||||
@ -602,6 +603,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
libc::NOTE_FFAND,
|
||||
@ -611,6 +613,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
libc::NOTE_FFOR,
|
||||
@ -620,6 +623,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
libc::NOTE_FFCOPY,
|
||||
@ -629,6 +633,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
libc::NOTE_FFCTRLMASK,
|
||||
@ -638,6 +643,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
libc::NOTE_FFLAGSMASK,
|
||||
@ -652,6 +658,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_EXTEND,
|
||||
@ -663,6 +670,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_NONE,
|
||||
@ -675,6 +683,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_SIGNAL,
|
||||
@ -682,6 +691,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_EXITSTATUS,
|
||||
@ -689,6 +699,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_EXIT_DETAIL,
|
||||
@ -719,6 +730,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_EXIT_DETAIL_MASK,
|
||||
@ -726,6 +738,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_EXIT_DECRYPTFAIL,
|
||||
@ -733,6 +746,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_EXIT_MEMORY,
|
||||
@ -740,6 +754,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_EXIT_CSERROR,
|
||||
@ -747,6 +762,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_VM_PRESSURE,
|
||||
@ -754,6 +770,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_VM_PRESSURE_TERMINATE,
|
||||
@ -761,6 +778,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_VM_PRESSURE_SUDDEN_TERMINATE,
|
||||
@ -768,6 +786,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_VM_ERROR,
|
||||
@ -776,6 +795,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_SECONDS,
|
||||
@ -786,6 +806,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_USECONDS,
|
||||
@ -794,6 +815,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_NSECONDS,
|
||||
@ -801,6 +823,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_ABSOLUTE,
|
||||
@ -808,6 +831,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_LEEWAY,
|
||||
@ -815,6 +839,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_CRITICAL,
|
||||
@ -822,6 +847,7 @@ pub mod event {
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos"
|
||||
))]
|
||||
libc::NOTE_BACKGROUND,
|
||||
@ -842,6 +868,14 @@ pub mod event {
|
||||
}
|
||||
}
|
||||
|
||||
// No special requirement from the implementation around waking.
|
||||
pub(crate) use crate::sys::unix::waker::Waker;
|
||||
|
||||
cfg_io_source! {
|
||||
mod stateless_io_source;
|
||||
pub(crate) use stateless_io_source::IoSourceState;
|
||||
}
|
||||
|
||||
#[test]
|
||||
#[cfg(feature = "os-ext")]
|
||||
fn does_not_register_rw() {
|
||||
|
@ -1,49 +0,0 @@
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "redox",
|
||||
))]
|
||||
mod epoll;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "android",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "redox",
|
||||
))]
|
||||
pub(crate) use self::epoll::{event, Event, Events, Selector};
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
mod kqueue;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
pub(crate) use self::kqueue::{event, Event, Events, Selector};
|
||||
|
||||
/// Lowest file descriptor used in `Selector::try_clone`.
|
||||
///
|
||||
/// # Notes
|
||||
///
|
||||
/// Usually fds 0, 1 and 2 are standard in, out and error. Some application
|
||||
/// blindly assume this to be true, which means using any one of those a select
|
||||
/// could result in some interesting and unexpected errors. Avoid that by using
|
||||
/// an fd that doesn't have a pre-determined usage.
|
||||
const LOWEST_FD: libc::c_int = 3;
|
749
third_party/rust/mio/src/sys/unix/selector/poll.rs
vendored
Normal file
749
third_party/rust/mio/src/sys/unix/selector/poll.rs
vendored
Normal file
@ -0,0 +1,749 @@
|
||||
// This implementation is based on the one in the `polling` crate.
|
||||
// Thanks to https://github.com/Kestrer for the original implementation!
|
||||
// Permission to use this code has been granted by original author:
|
||||
// https://github.com/tokio-rs/mio/pull/1602#issuecomment-1218441031
|
||||
|
||||
use std::collections::HashMap;
|
||||
use std::fmt::{Debug, Formatter};
|
||||
#[cfg(not(target_os = "hermit"))]
|
||||
use std::os::fd::{AsRawFd, RawFd};
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::{AsRawFd, RawFd};
|
||||
use std::sync::atomic::{AtomicBool, AtomicUsize, Ordering};
|
||||
use std::sync::{Arc, Condvar, Mutex};
|
||||
use std::time::Duration;
|
||||
use std::{cmp, fmt, io};
|
||||
|
||||
use crate::sys::unix::waker::Waker as WakerInternal;
|
||||
use crate::{Interest, Token};
|
||||
|
||||
/// Unique id for use as `SelectorId`.
|
||||
#[cfg(debug_assertions)]
|
||||
static NEXT_ID: AtomicUsize = AtomicUsize::new(1);
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Selector {
|
||||
state: Arc<SelectorState>,
|
||||
}
|
||||
|
||||
impl Selector {
|
||||
pub fn new() -> io::Result<Selector> {
|
||||
let state = SelectorState::new()?;
|
||||
|
||||
Ok(Selector {
|
||||
state: Arc::new(state),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn try_clone(&self) -> io::Result<Selector> {
|
||||
let state = self.state.clone();
|
||||
|
||||
Ok(Selector { state })
|
||||
}
|
||||
|
||||
pub fn select(&self, events: &mut Events, timeout: Option<Duration>) -> io::Result<()> {
|
||||
self.state.select(events, timeout)
|
||||
}
|
||||
|
||||
pub fn register(&self, fd: RawFd, token: Token, interests: Interest) -> io::Result<()> {
|
||||
self.state.register(fd, token, interests)
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub(crate) fn register_internal(
|
||||
&self,
|
||||
fd: RawFd,
|
||||
token: Token,
|
||||
interests: Interest,
|
||||
) -> io::Result<Arc<RegistrationRecord>> {
|
||||
self.state.register_internal(fd, token, interests)
|
||||
}
|
||||
|
||||
pub fn reregister(&self, fd: RawFd, token: Token, interests: Interest) -> io::Result<()> {
|
||||
self.state.reregister(fd, token, interests)
|
||||
}
|
||||
|
||||
pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
|
||||
self.state.deregister(fd)
|
||||
}
|
||||
|
||||
pub fn wake(&self, token: Token) -> io::Result<()> {
|
||||
self.state.wake(token)
|
||||
}
|
||||
|
||||
cfg_io_source! {
|
||||
#[cfg(debug_assertions)]
|
||||
pub fn id(&self) -> usize {
|
||||
self.state.id
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Interface to poll.
|
||||
#[derive(Debug)]
|
||||
struct SelectorState {
|
||||
/// File descriptors to poll.
|
||||
fds: Mutex<Fds>,
|
||||
|
||||
/// File descriptors which will be removed before the next poll call.
|
||||
///
|
||||
/// When a file descriptor is deregistered while a poll is running, we need to filter
|
||||
/// out all removed descriptors after that poll is finished running.
|
||||
pending_removal: Mutex<Vec<RawFd>>,
|
||||
|
||||
/// Token associated with Waker that have recently asked to wake. This will
|
||||
/// cause a synthetic behaviour where on any wakeup we add all pending tokens
|
||||
/// to the list of emitted events.
|
||||
pending_wake_token: Mutex<Option<Token>>,
|
||||
|
||||
/// Data is written to this to wake up the current instance of `wait`, which can occur when the
|
||||
/// user notifies it (in which case `notified` would have been set) or when an operation needs
|
||||
/// to occur (in which case `waiting_operations` would have been incremented).
|
||||
notify_waker: WakerInternal,
|
||||
|
||||
/// The number of operations (`add`, `modify` or `delete`) that are currently waiting on the
|
||||
/// mutex to become free. When this is nonzero, `wait` must be suspended until it reaches zero
|
||||
/// again.
|
||||
waiting_operations: AtomicUsize,
|
||||
/// The condition variable that gets notified when `waiting_operations` reaches zero or
|
||||
/// `notified` becomes true.
|
||||
///
|
||||
/// This is used with the `fds` mutex.
|
||||
operations_complete: Condvar,
|
||||
|
||||
/// This selectors id.
|
||||
#[cfg(debug_assertions)]
|
||||
#[allow(dead_code)]
|
||||
id: usize,
|
||||
}
|
||||
|
||||
/// The file descriptors to poll in a `Poller`.
|
||||
#[derive(Debug, Clone)]
|
||||
struct Fds {
|
||||
/// The list of `pollfds` taken by poll.
|
||||
///
|
||||
/// The first file descriptor is always present and is used to notify the poller.
|
||||
poll_fds: Vec<PollFd>,
|
||||
/// The map of each file descriptor to data associated with it. This does not include the file
|
||||
/// descriptors created by the internal notify waker.
|
||||
fd_data: HashMap<RawFd, FdData>,
|
||||
}
|
||||
|
||||
/// Transparent wrapper around `libc::pollfd`, used to support `Debug` derives without adding the
|
||||
/// `extra_traits` feature of `libc`.
|
||||
#[repr(transparent)]
|
||||
#[derive(Clone)]
|
||||
struct PollFd(libc::pollfd);
|
||||
|
||||
impl Debug for PollFd {
|
||||
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("pollfd")
|
||||
.field("fd", &self.0.fd)
|
||||
.field("events", &self.0.events)
|
||||
.field("revents", &self.0.revents)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
/// Data associated with a file descriptor in a poller.
|
||||
#[derive(Debug, Clone)]
|
||||
struct FdData {
|
||||
/// The index into `poll_fds` this file descriptor is.
|
||||
poll_fds_index: usize,
|
||||
/// The key of the `Event` associated with this file descriptor.
|
||||
token: Token,
|
||||
/// Used to communicate with IoSourceState when we need to internally deregister
|
||||
/// based on a closed fd.
|
||||
shared_record: Arc<RegistrationRecord>,
|
||||
}
|
||||
|
||||
impl SelectorState {
|
||||
pub fn new() -> io::Result<SelectorState> {
|
||||
let notify_waker = WakerInternal::new_unregistered()?;
|
||||
|
||||
Ok(Self {
|
||||
fds: Mutex::new(Fds {
|
||||
poll_fds: vec![PollFd(libc::pollfd {
|
||||
fd: notify_waker.as_raw_fd(),
|
||||
events: libc::POLLIN,
|
||||
revents: 0,
|
||||
})],
|
||||
fd_data: HashMap::new(),
|
||||
}),
|
||||
pending_removal: Mutex::new(Vec::new()),
|
||||
pending_wake_token: Mutex::new(None),
|
||||
notify_waker,
|
||||
waiting_operations: AtomicUsize::new(0),
|
||||
operations_complete: Condvar::new(),
|
||||
#[cfg(debug_assertions)]
|
||||
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn select(&self, events: &mut Events, timeout: Option<Duration>) -> io::Result<()> {
|
||||
events.clear();
|
||||
|
||||
let mut fds = self.fds.lock().unwrap();
|
||||
|
||||
// Keep track of fds that receive POLLHUP or POLLERR (i.e. won't receive further
|
||||
// events) and internally deregister them before they are externally deregister'd. See
|
||||
// IoSourceState below to track how the external deregister call will be handled
|
||||
// when this state occurs.
|
||||
let mut closed_raw_fds = Vec::new();
|
||||
|
||||
loop {
|
||||
// Complete all current operations.
|
||||
loop {
|
||||
if self.waiting_operations.load(Ordering::SeqCst) == 0 {
|
||||
break;
|
||||
}
|
||||
|
||||
fds = self.operations_complete.wait(fds).unwrap();
|
||||
}
|
||||
|
||||
// Perform the poll.
|
||||
trace!("Polling on {:?}", &fds);
|
||||
let num_events = poll(&mut fds.poll_fds, timeout)?;
|
||||
trace!("Poll finished: {:?}", &fds);
|
||||
|
||||
if num_events == 0 {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let waker_events = fds.poll_fds[0].0.revents;
|
||||
let notified = waker_events != 0;
|
||||
let mut num_fd_events = if notified { num_events - 1 } else { num_events };
|
||||
|
||||
let pending_wake_token = self.pending_wake_token.lock().unwrap().take();
|
||||
|
||||
if notified {
|
||||
self.notify_waker.ack_and_reset();
|
||||
if pending_wake_token.is_some() {
|
||||
num_fd_events += 1;
|
||||
}
|
||||
}
|
||||
|
||||
// We now check whether this poll was performed with descriptors which were pending
|
||||
// for removal and filter out any matching.
|
||||
let mut pending_removal_guard = self.pending_removal.lock().unwrap();
|
||||
let mut pending_removal = std::mem::replace(pending_removal_guard.as_mut(), Vec::new());
|
||||
drop(pending_removal_guard);
|
||||
|
||||
// Store the events if there were any.
|
||||
if num_fd_events > 0 {
|
||||
let fds = &mut *fds;
|
||||
|
||||
events.reserve(num_fd_events);
|
||||
|
||||
// Add synthetic events we picked up from calls to wake()
|
||||
if let Some(pending_wake_token) = pending_wake_token {
|
||||
events.push(Event {
|
||||
token: pending_wake_token,
|
||||
events: waker_events,
|
||||
});
|
||||
}
|
||||
|
||||
for fd_data in fds.fd_data.values_mut() {
|
||||
let PollFd(poll_fd) = &mut fds.poll_fds[fd_data.poll_fds_index];
|
||||
|
||||
if pending_removal.contains(&poll_fd.fd) {
|
||||
// Fd was removed while poll was running
|
||||
continue;
|
||||
}
|
||||
|
||||
if poll_fd.revents != 0 {
|
||||
// Store event
|
||||
events.push(Event {
|
||||
token: fd_data.token,
|
||||
events: poll_fd.revents,
|
||||
});
|
||||
|
||||
if poll_fd.revents & (libc::POLLHUP | libc::POLLERR) != 0 {
|
||||
pending_removal.push(poll_fd.fd);
|
||||
closed_raw_fds.push(poll_fd.fd);
|
||||
}
|
||||
|
||||
// Remove the interest which just got triggered the IoSourceState's do_io
|
||||
// wrapper used with this selector will add back the interest using
|
||||
// reregister.
|
||||
poll_fd.events &= !poll_fd.revents;
|
||||
|
||||
// Minor optimization to potentially avoid looping n times where n is the
|
||||
// number of input fds (i.e. we might loop between m and n times where m is
|
||||
// the number of fds with revents != 0).
|
||||
if events.len() == num_fd_events {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
break; // No more polling.
|
||||
}
|
||||
|
||||
// If we didn't break above it means we got woken up internally (for example for adding an fd), so we poll again.
|
||||
}
|
||||
|
||||
drop(fds);
|
||||
let _ = self.deregister_all(&closed_raw_fds);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn register(&self, fd: RawFd, token: Token, interests: Interest) -> io::Result<()> {
|
||||
self.register_internal(fd, token, interests).map(|_| ())
|
||||
}
|
||||
|
||||
pub fn register_internal(
|
||||
&self,
|
||||
fd: RawFd,
|
||||
token: Token,
|
||||
interests: Interest,
|
||||
) -> io::Result<Arc<RegistrationRecord>> {
|
||||
#[cfg(debug_assertions)]
|
||||
if fd == self.notify_waker.as_raw_fd() {
|
||||
return Err(io::Error::from(io::ErrorKind::InvalidInput));
|
||||
}
|
||||
|
||||
// We must handle the unlikely case that the following order of operations happens:
|
||||
//
|
||||
// register(1 as RawFd)
|
||||
// deregister(1 as RawFd)
|
||||
// register(1 as RawFd)
|
||||
// <poll happens>
|
||||
//
|
||||
// Fd's pending removal only get cleared when poll has been run. It is possible that
|
||||
// between registering and deregistering and then _again_ registering the file descriptor
|
||||
// poll never gets called, thus the fd stays stuck in the pending removal list.
|
||||
//
|
||||
// To avoid this scenario we remove an fd from pending removals when registering it.
|
||||
let mut pending_removal = self.pending_removal.lock().unwrap();
|
||||
if let Some(idx) = pending_removal.iter().position(|&pending| pending == fd) {
|
||||
pending_removal.swap_remove(idx);
|
||||
}
|
||||
drop(pending_removal);
|
||||
|
||||
self.modify_fds(|fds| {
|
||||
if fds.fd_data.contains_key(&fd) {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::AlreadyExists,
|
||||
"I/O source already registered this `Registry` \
|
||||
(an old file descriptor might have been closed without deregistration)",
|
||||
));
|
||||
}
|
||||
|
||||
let poll_fds_index = fds.poll_fds.len();
|
||||
let record = Arc::new(RegistrationRecord::new());
|
||||
fds.fd_data.insert(
|
||||
fd,
|
||||
FdData {
|
||||
poll_fds_index,
|
||||
token,
|
||||
shared_record: record.clone(),
|
||||
},
|
||||
);
|
||||
|
||||
fds.poll_fds.push(PollFd(libc::pollfd {
|
||||
fd,
|
||||
events: interests_to_poll(interests),
|
||||
revents: 0,
|
||||
}));
|
||||
|
||||
Ok(record)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn reregister(&self, fd: RawFd, token: Token, interests: Interest) -> io::Result<()> {
|
||||
self.modify_fds(|fds| {
|
||||
let data = fds.fd_data.get_mut(&fd).ok_or(io::ErrorKind::NotFound)?;
|
||||
data.token = token;
|
||||
let poll_fds_index = data.poll_fds_index;
|
||||
fds.poll_fds[poll_fds_index].0.events = interests_to_poll(interests);
|
||||
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
|
||||
pub fn deregister(&self, fd: RawFd) -> io::Result<()> {
|
||||
self.deregister_all(&[fd])
|
||||
.map_err(|_| io::ErrorKind::NotFound)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Perform a modification on `fds`, interrupting the current caller of `wait` if it's running.
|
||||
fn modify_fds<T>(&self, f: impl FnOnce(&mut Fds) -> T) -> T {
|
||||
self.waiting_operations.fetch_add(1, Ordering::SeqCst);
|
||||
|
||||
// Wake up the current caller of `wait` if there is one.
|
||||
let sent_notification = self.notify_waker.wake().is_ok();
|
||||
|
||||
let mut fds = self.fds.lock().unwrap();
|
||||
|
||||
// If there was no caller of `wait` our notification was not removed from the pipe.
|
||||
if sent_notification {
|
||||
self.notify_waker.ack_and_reset();
|
||||
}
|
||||
|
||||
let res = f(&mut *fds);
|
||||
|
||||
if self.waiting_operations.fetch_sub(1, Ordering::SeqCst) == 1 {
|
||||
self.operations_complete.notify_one();
|
||||
}
|
||||
|
||||
res
|
||||
}
|
||||
|
||||
/// Special optimized version of [Self::deregister] which handles multiple removals
|
||||
/// at once. Ok result if all removals were performed, Err if any entries
|
||||
/// were not found.
|
||||
fn deregister_all(&self, targets: &[RawFd]) -> Result<(), ()> {
|
||||
if targets.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let mut pending_removal = self.pending_removal.lock().unwrap();
|
||||
pending_removal.extend(targets);
|
||||
drop(pending_removal);
|
||||
|
||||
self.modify_fds(|fds| {
|
||||
let mut all_successful = true;
|
||||
|
||||
for target in targets {
|
||||
match fds.fd_data.remove(target).ok_or(()) {
|
||||
Ok(data) => {
|
||||
data.shared_record.mark_unregistered();
|
||||
fds.poll_fds.swap_remove(data.poll_fds_index);
|
||||
if let Some(swapped_pollfd) = fds.poll_fds.get(data.poll_fds_index) {
|
||||
fds.fd_data
|
||||
.get_mut(&swapped_pollfd.0.fd)
|
||||
.unwrap()
|
||||
.poll_fds_index = data.poll_fds_index;
|
||||
}
|
||||
}
|
||||
Err(_) => all_successful = false,
|
||||
}
|
||||
}
|
||||
|
||||
if all_successful {
|
||||
Ok(())
|
||||
} else {
|
||||
Err(())
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn wake(&self, token: Token) -> io::Result<()> {
|
||||
self.pending_wake_token.lock().unwrap().replace(token);
|
||||
self.notify_waker.wake()
|
||||
}
|
||||
}
|
||||
|
||||
/// Shared record between IoSourceState and SelectorState that allows us to internally
|
||||
/// deregister partially or fully closed fds (i.e. when we get POLLHUP or PULLERR) without
|
||||
/// confusing IoSourceState and trying to deregister twice. This isn't strictly
|
||||
/// required as technically deregister is idempotent but it is confusing
|
||||
/// when trying to debug behaviour as we get imbalanced calls to register/deregister and
|
||||
/// superfluous NotFound errors.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct RegistrationRecord {
|
||||
is_unregistered: AtomicBool,
|
||||
}
|
||||
|
||||
impl RegistrationRecord {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
is_unregistered: AtomicBool::new(false),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn mark_unregistered(&self) {
|
||||
self.is_unregistered.store(true, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn is_registered(&self) -> bool {
|
||||
!self.is_unregistered.load(Ordering::Relaxed)
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "linux")]
|
||||
const POLLRDHUP: libc::c_short = libc::POLLRDHUP;
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
const POLLRDHUP: libc::c_short = 0;
|
||||
|
||||
const READ_EVENTS: libc::c_short = libc::POLLIN | POLLRDHUP;
|
||||
|
||||
const WRITE_EVENTS: libc::c_short = libc::POLLOUT;
|
||||
|
||||
const PRIORITY_EVENTS: libc::c_short = libc::POLLPRI;
|
||||
|
||||
/// Get the input poll events for the given event.
|
||||
fn interests_to_poll(interest: Interest) -> libc::c_short {
|
||||
let mut kind = 0;
|
||||
|
||||
if interest.is_readable() {
|
||||
kind |= READ_EVENTS;
|
||||
}
|
||||
|
||||
if interest.is_writable() {
|
||||
kind |= WRITE_EVENTS;
|
||||
}
|
||||
|
||||
if interest.is_priority() {
|
||||
kind |= PRIORITY_EVENTS;
|
||||
}
|
||||
|
||||
kind
|
||||
}
|
||||
|
||||
/// Helper function to call poll.
|
||||
fn poll(fds: &mut [PollFd], timeout: Option<Duration>) -> io::Result<usize> {
|
||||
loop {
|
||||
// A bug in kernels < 2.6.37 makes timeouts larger than LONG_MAX / CONFIG_HZ
|
||||
// (approx. 30 minutes with CONFIG_HZ=1200) effectively infinite on 32 bits
|
||||
// architectures. The magic number is the same constant used by libuv.
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
const MAX_SAFE_TIMEOUT: u128 = 1789569;
|
||||
#[cfg(not(target_pointer_width = "32"))]
|
||||
const MAX_SAFE_TIMEOUT: u128 = libc::c_int::MAX as u128;
|
||||
|
||||
let timeout = timeout
|
||||
.map(|to| {
|
||||
// `Duration::as_millis` truncates, so round up. This avoids
|
||||
// turning sub-millisecond timeouts into a zero timeout, unless
|
||||
// the caller explicitly requests that by specifying a zero
|
||||
// timeout.
|
||||
let to_ms = to
|
||||
.checked_add(Duration::from_nanos(999_999))
|
||||
.unwrap_or(to)
|
||||
.as_millis();
|
||||
cmp::min(MAX_SAFE_TIMEOUT, to_ms) as libc::c_int
|
||||
})
|
||||
.unwrap_or(-1);
|
||||
|
||||
let res = syscall!(poll(
|
||||
fds.as_mut_ptr() as *mut libc::pollfd,
|
||||
fds.len() as libc::nfds_t,
|
||||
timeout,
|
||||
));
|
||||
|
||||
match res {
|
||||
Ok(num_events) => break Ok(num_events as usize),
|
||||
// poll returns EAGAIN if we can retry it.
|
||||
Err(e) if e.raw_os_error() == Some(libc::EAGAIN) => continue,
|
||||
Err(e) => return Err(e),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Event {
|
||||
token: Token,
|
||||
events: libc::c_short,
|
||||
}
|
||||
|
||||
pub type Events = Vec<Event>;
|
||||
|
||||
pub mod event {
|
||||
use std::fmt;
|
||||
|
||||
use crate::sys::Event;
|
||||
use crate::Token;
|
||||
|
||||
use super::POLLRDHUP;
|
||||
|
||||
pub fn token(event: &Event) -> Token {
|
||||
event.token
|
||||
}
|
||||
|
||||
pub fn is_readable(event: &Event) -> bool {
|
||||
(event.events & libc::POLLIN) != 0 || (event.events & libc::POLLPRI) != 0
|
||||
}
|
||||
|
||||
pub fn is_writable(event: &Event) -> bool {
|
||||
(event.events & libc::POLLOUT) != 0
|
||||
}
|
||||
|
||||
pub fn is_error(event: &Event) -> bool {
|
||||
(event.events & libc::POLLERR) != 0
|
||||
}
|
||||
|
||||
pub fn is_read_closed(event: &Event) -> bool {
|
||||
// Both halves of the socket have closed
|
||||
(event.events & libc::POLLHUP) != 0
|
||||
// Socket has received FIN or called shutdown(SHUT_RD)
|
||||
|| (event.events & POLLRDHUP) != 0
|
||||
}
|
||||
|
||||
pub fn is_write_closed(event: &Event) -> bool {
|
||||
// Both halves of the socket have closed
|
||||
(event.events & libc::POLLHUP) != 0
|
||||
// Unix pipe write end has closed
|
||||
|| ((event.events & libc::POLLOUT) != 0 && (event.events & libc::POLLERR) != 0)
|
||||
// The other side (read end) of a Unix pipe has closed.
|
||||
|| (event.events == libc::POLLERR)
|
||||
}
|
||||
|
||||
pub fn is_priority(event: &Event) -> bool {
|
||||
(event.events & libc::POLLPRI) != 0
|
||||
}
|
||||
|
||||
pub fn is_aio(_: &Event) -> bool {
|
||||
// Not supported in the kernel, only in libc.
|
||||
false
|
||||
}
|
||||
|
||||
pub fn is_lio(_: &Event) -> bool {
|
||||
// Not supported.
|
||||
false
|
||||
}
|
||||
|
||||
pub fn debug_details(f: &mut fmt::Formatter<'_>, event: &Event) -> fmt::Result {
|
||||
#[allow(clippy::trivially_copy_pass_by_ref)]
|
||||
fn check_events(got: &libc::c_short, want: &libc::c_short) -> bool {
|
||||
(*got & want) != 0
|
||||
}
|
||||
debug_detail!(
|
||||
EventsDetails(libc::c_short),
|
||||
check_events,
|
||||
libc::POLLIN,
|
||||
libc::POLLPRI,
|
||||
libc::POLLOUT,
|
||||
libc::POLLRDNORM,
|
||||
libc::POLLRDBAND,
|
||||
libc::POLLWRNORM,
|
||||
libc::POLLWRBAND,
|
||||
libc::POLLERR,
|
||||
libc::POLLHUP,
|
||||
);
|
||||
|
||||
f.debug_struct("poll_event")
|
||||
.field("token", &event.token)
|
||||
.field("events", &EventsDetails(event.events))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Waker {
|
||||
selector: Selector,
|
||||
token: Token,
|
||||
}
|
||||
|
||||
impl Waker {
|
||||
pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
|
||||
Ok(Waker {
|
||||
selector: selector.try_clone()?,
|
||||
token,
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn wake(&self) -> io::Result<()> {
|
||||
self.selector.wake(self.token)
|
||||
}
|
||||
}
|
||||
|
||||
cfg_io_source! {
|
||||
use crate::Registry;
|
||||
|
||||
struct InternalState {
|
||||
selector: Selector,
|
||||
token: Token,
|
||||
interests: Interest,
|
||||
fd: RawFd,
|
||||
shared_record: Arc<RegistrationRecord>,
|
||||
}
|
||||
|
||||
impl Drop for InternalState {
|
||||
fn drop(&mut self) {
|
||||
if self.shared_record.is_registered() {
|
||||
let _ = self.selector.deregister(self.fd);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct IoSourceState {
|
||||
inner: Option<Box<InternalState>>,
|
||||
}
|
||||
|
||||
impl IoSourceState {
|
||||
pub fn new() -> IoSourceState {
|
||||
IoSourceState { inner: None }
|
||||
}
|
||||
|
||||
pub fn do_io<T, F, R>(&self, f: F, io: &T) -> io::Result<R>
|
||||
where
|
||||
F: FnOnce(&T) -> io::Result<R>,
|
||||
{
|
||||
let result = f(io);
|
||||
|
||||
if let Err(err) = &result {
|
||||
if err.kind() == io::ErrorKind::WouldBlock {
|
||||
self.inner.as_ref().map_or(Ok(()), |state| {
|
||||
state
|
||||
.selector
|
||||
.reregister(state.fd, state.token, state.interests)
|
||||
})?;
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn register(
|
||||
&mut self,
|
||||
registry: &Registry,
|
||||
token: Token,
|
||||
interests: Interest,
|
||||
fd: RawFd,
|
||||
) -> io::Result<()> {
|
||||
if self.inner.is_some() {
|
||||
Err(io::ErrorKind::AlreadyExists.into())
|
||||
} else {
|
||||
let selector = registry.selector().try_clone()?;
|
||||
|
||||
selector.register_internal(fd, token, interests).map(move |shared_record| {
|
||||
let state = InternalState {
|
||||
selector,
|
||||
token,
|
||||
interests,
|
||||
fd,
|
||||
shared_record,
|
||||
};
|
||||
|
||||
self.inner = Some(Box::new(state));
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reregister(
|
||||
&mut self,
|
||||
registry: &Registry,
|
||||
token: Token,
|
||||
interests: Interest,
|
||||
fd: RawFd,
|
||||
) -> io::Result<()> {
|
||||
match self.inner.as_mut() {
|
||||
Some(state) => registry
|
||||
.selector()
|
||||
.reregister(fd, token, interests)
|
||||
.map(|()| {
|
||||
state.token = token;
|
||||
state.interests = interests;
|
||||
}),
|
||||
None => Err(io::ErrorKind::NotFound.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn deregister(&mut self, registry: &Registry, fd: RawFd) -> io::Result<()> {
|
||||
if let Some(state) = self.inner.take() {
|
||||
// Marking unregistered will short circuit the drop behaviour of calling
|
||||
// deregister so the call to deregister below is strictly required.
|
||||
state.shared_record.mark_unregistered();
|
||||
}
|
||||
|
||||
registry.selector().deregister(fd)
|
||||
}
|
||||
}
|
||||
}
|
50
third_party/rust/mio/src/sys/unix/selector/stateless_io_source.rs
vendored
Normal file
50
third_party/rust/mio/src/sys/unix/selector/stateless_io_source.rs
vendored
Normal file
@ -0,0 +1,50 @@
|
||||
//! Both `kqueue(2)` and `epoll(2)` don't need to hold any user space state.
|
||||
|
||||
use std::io;
|
||||
use std::os::fd::RawFd;
|
||||
|
||||
use crate::{Interest, Registry, Token};
|
||||
|
||||
pub(crate) struct IoSourceState;
|
||||
|
||||
impl IoSourceState {
|
||||
pub(crate) fn new() -> IoSourceState {
|
||||
IoSourceState
|
||||
}
|
||||
|
||||
pub(crate) fn do_io<T, F, R>(&self, f: F, io: &T) -> io::Result<R>
|
||||
where
|
||||
F: FnOnce(&T) -> io::Result<R>,
|
||||
{
|
||||
// We don't hold state, so we can just call the function and
|
||||
// return.
|
||||
f(io)
|
||||
}
|
||||
|
||||
pub(crate) fn register(
|
||||
&mut self,
|
||||
registry: &Registry,
|
||||
token: Token,
|
||||
interests: Interest,
|
||||
fd: RawFd,
|
||||
) -> io::Result<()> {
|
||||
// Pass through, we don't have any state.
|
||||
registry.selector().register(fd, token, interests)
|
||||
}
|
||||
|
||||
pub(crate) fn reregister(
|
||||
&mut self,
|
||||
registry: &Registry,
|
||||
token: Token,
|
||||
interests: Interest,
|
||||
fd: RawFd,
|
||||
) -> io::Result<()> {
|
||||
// Pass through, we don't have any state.
|
||||
registry.selector().reregister(fd, token, interests)
|
||||
}
|
||||
|
||||
pub(crate) fn deregister(&mut self, registry: &Registry, fd: RawFd) -> io::Result<()> {
|
||||
// Pass through, we don't have any state.
|
||||
registry.selector().deregister(fd)
|
||||
}
|
||||
}
|
15
third_party/rust/mio/src/sys/unix/sourcefd.rs
vendored
15
third_party/rust/mio/src/sys/unix/sourcefd.rs
vendored
@ -1,7 +1,12 @@
|
||||
use crate::{event, Interest, Registry, Token};
|
||||
|
||||
use std::io;
|
||||
use std::os::unix::io::RawFd;
|
||||
#[cfg(not(target_os = "hermit"))]
|
||||
use std::os::fd::RawFd;
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::RawFd;
|
||||
|
||||
use crate::{event, Interest, Registry, Token};
|
||||
|
||||
/// Adapter for [`RawFd`] providing an [`event::Source`] implementation.
|
||||
///
|
||||
@ -38,7 +43,7 @@ use std::os::unix::io::RawFd;
|
||||
/// use mio::{Interest, Poll, Token};
|
||||
/// use mio::unix::SourceFd;
|
||||
///
|
||||
/// use std::os::unix::io::AsRawFd;
|
||||
/// use std::os::fd::AsRawFd;
|
||||
/// use std::net::TcpListener;
|
||||
///
|
||||
/// // Bind a std listener
|
||||
@ -62,7 +67,7 @@ use std::os::unix::io::RawFd;
|
||||
/// use mio::{event, Interest, Registry, Token};
|
||||
/// use mio::unix::SourceFd;
|
||||
///
|
||||
/// use std::os::unix::io::RawFd;
|
||||
/// use std::os::fd::RawFd;
|
||||
/// use std::io;
|
||||
///
|
||||
/// # #[allow(dead_code)]
|
||||
|
30
third_party/rust/mio/src/sys/unix/tcp.rs
vendored
30
third_party/rust/mio/src/sys/unix/tcp.rs
vendored
@ -2,7 +2,12 @@ use std::convert::TryInto;
|
||||
use std::io;
|
||||
use std::mem::{size_of, MaybeUninit};
|
||||
use std::net::{self, SocketAddr};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd};
|
||||
#[cfg(not(target_os = "hermit"))]
|
||||
use std::os::fd::{AsRawFd, FromRawFd};
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::{AsRawFd, FromRawFd};
|
||||
|
||||
use crate::sys::unix::net::{new_socket, socket_addr, to_socket_addr};
|
||||
|
||||
@ -34,7 +39,7 @@ pub(crate) fn connect(socket: &net::TcpStream, addr: SocketAddr) -> io::Result<(
|
||||
}
|
||||
|
||||
pub(crate) fn listen(socket: &net::TcpListener, backlog: u32) -> io::Result<()> {
|
||||
let backlog = backlog.try_into().unwrap_or(i32::max_value());
|
||||
let backlog = backlog.try_into().unwrap_or(i32::MAX);
|
||||
syscall!(listen(socket.as_raw_fd(), backlog))?;
|
||||
Ok(())
|
||||
}
|
||||
@ -63,10 +68,13 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream,
|
||||
all(not(target_arch="x86"), target_os = "android"),
|
||||
target_os = "dragonfly",
|
||||
target_os = "freebsd",
|
||||
target_os = "fuchsia",
|
||||
target_os = "hurd",
|
||||
target_os = "illumos",
|
||||
target_os = "linux",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "solaris",
|
||||
))]
|
||||
let stream = {
|
||||
syscall!(accept4(
|
||||
@ -79,14 +87,21 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream,
|
||||
}?;
|
||||
|
||||
// But not all platforms have the `accept4(2)` call. Luckily BSD (derived)
|
||||
// OSes inherit the non-blocking flag from the listener, so we just have to
|
||||
// OSs inherit the non-blocking flag from the listener, so we just have to
|
||||
// set `CLOEXEC`.
|
||||
#[cfg(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "redox",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "hermit",
|
||||
target_os = "nto",
|
||||
all(target_arch = "x86", target_os = "android"),
|
||||
))]
|
||||
let stream = {
|
||||
@ -97,10 +112,17 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream,
|
||||
))
|
||||
.map(|socket| unsafe { net::TcpStream::from_raw_fd(socket) })
|
||||
.and_then(|s| {
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "vita")))]
|
||||
syscall!(fcntl(s.as_raw_fd(), libc::F_SETFD, libc::FD_CLOEXEC))?;
|
||||
|
||||
// See https://github.com/tokio-rs/mio/issues/1450
|
||||
#[cfg(all(target_arch = "x86", target_os = "android"))]
|
||||
#[cfg(any(
|
||||
all(target_arch = "x86", target_os = "android"),
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "hermit",
|
||||
target_os = "nto",
|
||||
))]
|
||||
syscall!(fcntl(s.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK))?;
|
||||
|
||||
Ok(s)
|
||||
|
11
third_party/rust/mio/src/sys/unix/udp.rs
vendored
11
third_party/rust/mio/src/sys/unix/udp.rs
vendored
@ -1,9 +1,14 @@
|
||||
use crate::sys::unix::net::{new_ip_socket, socket_addr};
|
||||
|
||||
use std::io;
|
||||
use std::mem;
|
||||
use std::net::{self, SocketAddr};
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd};
|
||||
#[cfg(not(target_os = "hermit"))]
|
||||
use std::os::fd::{AsRawFd, FromRawFd};
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::{AsRawFd, FromRawFd};
|
||||
|
||||
use crate::sys::unix::net::{new_ip_socket, socket_addr};
|
||||
|
||||
pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> {
|
||||
let fd = new_ip_socket(addr, libc::SOCK_DGRAM)?;
|
||||
|
@ -1,17 +1,16 @@
|
||||
use super::{socket_addr, SocketAddr};
|
||||
use crate::sys::unix::net::new_socket;
|
||||
|
||||
use std::io;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd};
|
||||
use std::os::unix::net;
|
||||
use std::path::Path;
|
||||
use std::os::fd::{AsRawFd, FromRawFd};
|
||||
use std::os::unix::net::{self, SocketAddr};
|
||||
|
||||
pub(crate) fn bind(path: &Path) -> io::Result<net::UnixDatagram> {
|
||||
let (sockaddr, socklen) = socket_addr(path)?;
|
||||
let sockaddr = &sockaddr as *const libc::sockaddr_un as *const _;
|
||||
use crate::sys::unix::net::new_socket;
|
||||
use crate::sys::unix::uds::unix_addr;
|
||||
|
||||
pub(crate) fn bind_addr(address: &SocketAddr) -> io::Result<net::UnixDatagram> {
|
||||
let socket = unbound()?;
|
||||
syscall!(bind(socket.as_raw_fd(), sockaddr, socklen))?;
|
||||
|
||||
let (unix_address, addrlen) = unix_addr(address);
|
||||
let sockaddr = &unix_address as *const libc::sockaddr_un as *const libc::sockaddr;
|
||||
syscall!(bind(socket.as_raw_fd(), sockaddr, addrlen))?;
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
@ -24,33 +23,3 @@ pub(crate) fn unbound() -> io::Result<net::UnixDatagram> {
|
||||
pub(crate) fn pair() -> io::Result<(net::UnixDatagram, net::UnixDatagram)> {
|
||||
super::pair(libc::SOCK_DGRAM)
|
||||
}
|
||||
|
||||
pub(crate) fn local_addr(socket: &net::UnixDatagram) -> io::Result<SocketAddr> {
|
||||
super::local_addr(socket.as_raw_fd())
|
||||
}
|
||||
|
||||
pub(crate) fn peer_addr(socket: &net::UnixDatagram) -> io::Result<SocketAddr> {
|
||||
super::peer_addr(socket.as_raw_fd())
|
||||
}
|
||||
|
||||
pub(crate) fn recv_from(
|
||||
socket: &net::UnixDatagram,
|
||||
dst: &mut [u8],
|
||||
) -> io::Result<(usize, SocketAddr)> {
|
||||
let mut count = 0;
|
||||
let socketaddr = SocketAddr::new(|sockaddr, socklen| {
|
||||
syscall!(recvfrom(
|
||||
socket.as_raw_fd(),
|
||||
dst.as_mut_ptr() as *mut _,
|
||||
dst.len(),
|
||||
0,
|
||||
sockaddr,
|
||||
socklen,
|
||||
))
|
||||
.map(|c| {
|
||||
count = c;
|
||||
c as libc::c_int
|
||||
})
|
||||
})?;
|
||||
Ok((count as usize, socketaddr))
|
||||
}
|
||||
|
@ -1,46 +1,51 @@
|
||||
use super::socket_addr;
|
||||
use crate::net::{SocketAddr, UnixStream};
|
||||
use crate::sys::unix::net::new_socket;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd};
|
||||
use std::os::unix::net;
|
||||
use std::ffi::OsStr;
|
||||
use std::os::fd::{AsRawFd, FromRawFd};
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::os::unix::net::{self, SocketAddr};
|
||||
use std::path::Path;
|
||||
use std::{io, mem};
|
||||
|
||||
pub(crate) fn bind(path: &Path) -> io::Result<net::UnixListener> {
|
||||
let (sockaddr, socklen) = socket_addr(path)?;
|
||||
let sockaddr = &sockaddr as *const libc::sockaddr_un as *const libc::sockaddr;
|
||||
use crate::net::UnixStream;
|
||||
use crate::sys::unix::net::new_socket;
|
||||
use crate::sys::unix::uds::{path_offset, unix_addr};
|
||||
|
||||
pub(crate) fn bind_addr(address: &SocketAddr) -> io::Result<net::UnixListener> {
|
||||
let fd = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?;
|
||||
let socket = unsafe { net::UnixListener::from_raw_fd(fd) };
|
||||
syscall!(bind(fd, sockaddr, socklen))?;
|
||||
|
||||
let (unix_address, addrlen) = unix_addr(address);
|
||||
let sockaddr = &unix_address as *const libc::sockaddr_un as *const libc::sockaddr;
|
||||
syscall!(bind(fd, sockaddr, addrlen))?;
|
||||
syscall!(listen(fd, 1024))?;
|
||||
|
||||
Ok(socket)
|
||||
}
|
||||
|
||||
pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, SocketAddr)> {
|
||||
let sockaddr = mem::MaybeUninit::<libc::sockaddr_un>::zeroed();
|
||||
|
||||
// This is safe to assume because a `libc::sockaddr_un` filled with `0`
|
||||
// bytes is properly initialized.
|
||||
// SAFETY: `libc::sockaddr_un` zero filled is properly initialized.
|
||||
//
|
||||
// `0` is a valid value for `sockaddr_un::sun_family`; it is
|
||||
// `libc::AF_UNSPEC`.
|
||||
//
|
||||
// `[0; 108]` is a valid value for `sockaddr_un::sun_path`; it begins an
|
||||
// abstract path.
|
||||
let mut sockaddr = unsafe { sockaddr.assume_init() };
|
||||
let mut sockaddr = unsafe { mem::zeroed::<libc::sockaddr_un>() };
|
||||
|
||||
sockaddr.sun_family = libc::AF_UNIX as libc::sa_family_t;
|
||||
let mut socklen = mem::size_of_val(&sockaddr) as libc::socklen_t;
|
||||
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "redox",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "nto",
|
||||
// Android x86's seccomp profile forbids calls to `accept4(2)`
|
||||
// See https://github.com/tokio-rs/mio/issues/1445 for details
|
||||
all(target_arch = "x86", target_os = "android"),
|
||||
@ -57,12 +62,18 @@ pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, So
|
||||
};
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "netbsd",
|
||||
target_os = "redox",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "nto",
|
||||
all(target_arch = "x86", target_os = "android")
|
||||
))]
|
||||
let socket = syscall!(accept(
|
||||
@ -74,20 +85,37 @@ pub(crate) fn accept(listener: &net::UnixListener) -> io::Result<(UnixStream, So
|
||||
// Ensure the socket is closed if either of the `fcntl` calls
|
||||
// error below.
|
||||
let s = unsafe { net::UnixStream::from_raw_fd(socket) };
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "vita")))]
|
||||
syscall!(fcntl(socket, libc::F_SETFD, libc::FD_CLOEXEC))?;
|
||||
|
||||
// See https://github.com/tokio-rs/mio/issues/1450
|
||||
#[cfg(all(target_arch = "x86", target_os = "android"))]
|
||||
#[cfg(any(
|
||||
all(target_arch = "x86", target_os = "android"),
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
target_os = "nto",
|
||||
))]
|
||||
syscall!(fcntl(socket, libc::F_SETFL, libc::O_NONBLOCK))?;
|
||||
|
||||
Ok(s)
|
||||
});
|
||||
|
||||
socket
|
||||
.map(UnixStream::from_std)
|
||||
.map(|stream| (stream, SocketAddr::from_parts(sockaddr, socklen)))
|
||||
}
|
||||
let socket = socket.map(UnixStream::from_std)?;
|
||||
|
||||
pub(crate) fn local_addr(listener: &net::UnixListener) -> io::Result<SocketAddr> {
|
||||
super::local_addr(listener.as_raw_fd())
|
||||
#[allow(unused_mut)] // See below.
|
||||
let mut path_len = socklen as usize - path_offset(&sockaddr);
|
||||
// On FreeBSD and Darwin, it returns a length of 14/16, but an unnamed (all
|
||||
// zero) address. Map that to a length of 0 to match other OS.
|
||||
if sockaddr.sun_path[0] == 0 {
|
||||
path_len = 0;
|
||||
}
|
||||
// SAFETY: going from i8 to u8 is fine in this context.
|
||||
let mut path =
|
||||
unsafe { &*(&sockaddr.sun_path[..path_len] as *const [libc::c_char] as *const [u8]) };
|
||||
// Remove last null as `SocketAddr::from_pathname` doesn't accept it.
|
||||
if let Some(0) = path.last() {
|
||||
path = &path[..path.len() - 1];
|
||||
}
|
||||
let address = SocketAddr::from_pathname(Path::new(OsStr::from_bytes(path)))?;
|
||||
Ok((socket, address))
|
||||
}
|
||||
|
275
third_party/rust/mio/src/sys/unix/uds/mod.rs
vendored
275
third_party/rust/mio/src/sys/unix/uds/mod.rs
vendored
@ -1,5 +1,17 @@
|
||||
mod socketaddr;
|
||||
pub use self::socketaddr::SocketAddr;
|
||||
#[cfg(target_os = "android")]
|
||||
use std::os::android::net::SocketAddrExt;
|
||||
#[cfg(target_os = "linux")]
|
||||
use std::os::linux::net::SocketAddrExt;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::os::unix::io::FromRawFd;
|
||||
use std::os::unix::net::SocketAddr;
|
||||
use std::{io, mem, ptr};
|
||||
|
||||
pub(crate) mod datagram;
|
||||
pub(crate) mod listener;
|
||||
pub(crate) mod stream;
|
||||
|
||||
const UNNAMED_ADDRESS: &[u8] = &[];
|
||||
|
||||
/// Get the `sun_path` field offset of `sockaddr_un` for the target OS.
|
||||
///
|
||||
@ -7,153 +19,156 @@ pub use self::socketaddr::SocketAddr;
|
||||
/// `size_of::<sa_family_t>()`, but some other implementations include
|
||||
/// other fields before `sun_path`, so the expression more portably
|
||||
/// describes the size of the address structure.
|
||||
pub(in crate::sys) fn path_offset(sockaddr: &libc::sockaddr_un) -> usize {
|
||||
fn path_offset(sockaddr: &libc::sockaddr_un) -> usize {
|
||||
let base = sockaddr as *const _ as usize;
|
||||
let path = &sockaddr.sun_path as *const _ as usize;
|
||||
path - base
|
||||
}
|
||||
|
||||
cfg_os_poll! {
|
||||
use std::cmp::Ordering;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::os::unix::io::{RawFd, FromRawFd};
|
||||
use std::path::Path;
|
||||
use std::{io, mem};
|
||||
/// Converts a Rust `SocketAddr` into the system representation.
|
||||
fn unix_addr(address: &SocketAddr) -> (libc::sockaddr_un, libc::socklen_t) {
|
||||
// SAFETY: `libc::sockaddr_un` zero filled is properly initialized.
|
||||
//
|
||||
// `0` is a valid value for `sockaddr_un::sun_family`; it is
|
||||
// `libc::AF_UNSPEC`.
|
||||
//
|
||||
// `[0; 108]` is a valid value for `sockaddr_un::sun_path`; it begins an
|
||||
// abstract path.
|
||||
let mut sockaddr = unsafe { mem::zeroed::<libc::sockaddr_un>() };
|
||||
|
||||
pub(crate) mod datagram;
|
||||
pub(crate) mod listener;
|
||||
pub(crate) mod stream;
|
||||
sockaddr.sun_family = libc::AF_UNIX as libc::sa_family_t;
|
||||
|
||||
pub(in crate::sys) fn socket_addr(path: &Path) -> io::Result<(libc::sockaddr_un, libc::socklen_t)> {
|
||||
let sockaddr = mem::MaybeUninit::<libc::sockaddr_un>::zeroed();
|
||||
|
||||
// This is safe to assume because a `libc::sockaddr_un` filled with `0`
|
||||
// bytes is properly initialized.
|
||||
//
|
||||
// `0` is a valid value for `sockaddr_un::sun_family`; it is
|
||||
// `libc::AF_UNSPEC`.
|
||||
//
|
||||
// `[0; 108]` is a valid value for `sockaddr_un::sun_path`; it begins an
|
||||
// abstract path.
|
||||
let mut sockaddr = unsafe { sockaddr.assume_init() };
|
||||
|
||||
sockaddr.sun_family = libc::AF_UNIX as libc::sa_family_t;
|
||||
|
||||
let bytes = path.as_os_str().as_bytes();
|
||||
match (bytes.first(), bytes.len().cmp(&sockaddr.sun_path.len())) {
|
||||
// Abstract paths don't need a null terminator
|
||||
(Some(&0), Ordering::Greater) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"path must be no longer than libc::sockaddr_un.sun_path",
|
||||
));
|
||||
#[allow(unused_mut)] // Only used with abstract namespaces.
|
||||
let mut offset = 0;
|
||||
let addr = match address.as_pathname() {
|
||||
Some(path) => path.as_os_str().as_bytes(),
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
None => match address.as_abstract_name() {
|
||||
Some(name) => {
|
||||
offset += 1;
|
||||
name
|
||||
}
|
||||
(_, Ordering::Greater) | (_, Ordering::Equal) => {
|
||||
return Err(io::Error::new(
|
||||
io::ErrorKind::InvalidInput,
|
||||
"path must be shorter than libc::sockaddr_un.sun_path",
|
||||
));
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
None => UNNAMED_ADDRESS,
|
||||
},
|
||||
#[cfg(not(any(target_os = "android", target_os = "linux")))]
|
||||
None => UNNAMED_ADDRESS,
|
||||
};
|
||||
|
||||
for (dst, src) in sockaddr.sun_path.iter_mut().zip(bytes.iter()) {
|
||||
*dst = *src as libc::c_char;
|
||||
}
|
||||
// SAFETY: `addr` and `sockaddr.sun_path` are not overlapping and both point
|
||||
// to valid memory.
|
||||
// SAFETY: since `addr` is a valid Unix address, it must not be larger than
|
||||
// `SUN_LEN` bytes, thus we won't overwrite the size of sockaddr.sun_path.
|
||||
// SAFETY: null byte is already written because we zeroed the address above.
|
||||
debug_assert!(offset + addr.len() <= sockaddr.sun_path.len());
|
||||
unsafe {
|
||||
ptr::copy_nonoverlapping(
|
||||
addr.as_ptr(),
|
||||
sockaddr.sun_path.as_mut_ptr().add(offset).cast(),
|
||||
addr.len(),
|
||||
)
|
||||
};
|
||||
|
||||
let offset = path_offset(&sockaddr);
|
||||
let mut socklen = offset + bytes.len();
|
||||
|
||||
match bytes.first() {
|
||||
// The struct has already been zeroes so the null byte for pathname
|
||||
// addresses is already there.
|
||||
Some(&0) | None => {}
|
||||
Some(_) => socklen += 1,
|
||||
}
|
||||
|
||||
Ok((sockaddr, socklen as libc::socklen_t))
|
||||
let mut addrlen = path_offset(&sockaddr) + addr.len();
|
||||
// +1 for null byte at the end of the path, not needed for abstract
|
||||
// namespaces (which start with a null byte).
|
||||
match addr.first() {
|
||||
Some(&0) | None => {}
|
||||
Some(_) => addrlen += 1,
|
||||
}
|
||||
|
||||
fn pair<T>(flags: libc::c_int) -> io::Result<(T, T)>
|
||||
where T: FromRawFd,
|
||||
// SAFETY: the length is fine to cast to `socklen_t` as it's 32 bits and the
|
||||
// address can be at most `SUN_LEN` bytes.
|
||||
(sockaddr, addrlen as _)
|
||||
}
|
||||
|
||||
fn pair<T>(flags: libc::c_int) -> io::Result<(T, T)>
|
||||
where
|
||||
T: FromRawFd,
|
||||
{
|
||||
#[cfg(not(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "nto",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
)))]
|
||||
let flags = flags | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
|
||||
|
||||
let mut fds = [-1; 2];
|
||||
syscall!(socketpair(libc::AF_UNIX, flags, 0, fds.as_mut_ptr()))?;
|
||||
let pair = unsafe { (T::from_raw_fd(fds[0]), T::from_raw_fd(fds[1])) };
|
||||
|
||||
// Darwin (and others) doesn't have SOCK_NONBLOCK or SOCK_CLOEXEC.
|
||||
//
|
||||
// In order to set those flags, additional `fcntl` sys calls must be
|
||||
// performed. If a `fnctl` fails after the sockets have been created,
|
||||
// the file descriptors will leak. Creating `pair` above ensures that if
|
||||
// there is an error, the file descriptors are closed.
|
||||
#[cfg(any(
|
||||
target_os = "aix",
|
||||
target_os = "haiku",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "nto",
|
||||
target_os = "tvos",
|
||||
target_os = "visionos",
|
||||
target_os = "watchos",
|
||||
target_os = "espidf",
|
||||
target_os = "vita",
|
||||
))]
|
||||
{
|
||||
#[cfg(not(any(
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
)))]
|
||||
let flags = flags | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;
|
||||
|
||||
let mut fds = [-1; 2];
|
||||
syscall!(socketpair(libc::AF_UNIX, flags, 0, fds.as_mut_ptr()))?;
|
||||
let pair = unsafe { (T::from_raw_fd(fds[0]), T::from_raw_fd(fds[1])) };
|
||||
|
||||
// Darwin doesn't have SOCK_NONBLOCK or SOCK_CLOEXEC.
|
||||
//
|
||||
// In order to set those flags, additional `fcntl` sys calls must be
|
||||
// performed. If a `fnctl` fails after the sockets have been created,
|
||||
// the file descriptors will leak. Creating `pair` above ensures that if
|
||||
// there is an error, the file descriptors are closed.
|
||||
#[cfg(any(
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
{
|
||||
syscall!(fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK))?;
|
||||
syscall!(fcntl(fds[0], libc::F_SETFD, libc::FD_CLOEXEC))?;
|
||||
syscall!(fcntl(fds[1], libc::F_SETFL, libc::O_NONBLOCK))?;
|
||||
syscall!(fcntl(fds[1], libc::F_SETFD, libc::FD_CLOEXEC))?;
|
||||
}
|
||||
Ok(pair)
|
||||
syscall!(fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK))?;
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "vita", target_os = "nto")))]
|
||||
syscall!(fcntl(fds[0], libc::F_SETFD, libc::FD_CLOEXEC))?;
|
||||
syscall!(fcntl(fds[1], libc::F_SETFL, libc::O_NONBLOCK))?;
|
||||
#[cfg(not(any(target_os = "espidf", target_os = "vita", target_os = "nto")))]
|
||||
syscall!(fcntl(fds[1], libc::F_SETFD, libc::FD_CLOEXEC))?;
|
||||
}
|
||||
|
||||
// The following functions can't simply be replaced with a call to
|
||||
// `net::UnixDatagram` because of our `SocketAddr` type.
|
||||
Ok(pair)
|
||||
}
|
||||
|
||||
fn local_addr(socket: RawFd) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|sockaddr, socklen| syscall!(getsockname(socket, sockaddr, socklen)))
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::os::unix::net::SocketAddr;
|
||||
use std::path::Path;
|
||||
use std::str;
|
||||
|
||||
use super::{path_offset, unix_addr};
|
||||
|
||||
#[test]
|
||||
fn pathname_address() {
|
||||
const PATH: &str = "./foo/bar.txt";
|
||||
const PATH_LEN: usize = 13;
|
||||
|
||||
// Pathname addresses do have a null terminator, so `socklen` is
|
||||
// expected to be `PATH_LEN` + `offset` + 1.
|
||||
let address = SocketAddr::from_pathname(Path::new(PATH)).unwrap();
|
||||
let (sockaddr, actual) = unix_addr(&address);
|
||||
let offset = path_offset(&sockaddr);
|
||||
let expected = PATH_LEN + offset + 1;
|
||||
assert_eq!(expected as libc::socklen_t, actual)
|
||||
}
|
||||
|
||||
fn peer_addr(socket: RawFd) -> io::Result<SocketAddr> {
|
||||
SocketAddr::new(|sockaddr, socklen| syscall!(getpeername(socket, sockaddr, socklen)))
|
||||
}
|
||||
#[test]
|
||||
#[cfg(any(target_os = "android", target_os = "linux"))]
|
||||
fn abstract_address() {
|
||||
use std::os::linux::net::SocketAddrExt;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::{path_offset, socket_addr};
|
||||
use std::path::Path;
|
||||
use std::str;
|
||||
const PATH: &[u8] = &[0, 116, 111, 107, 105, 111];
|
||||
const PATH_LEN: usize = 6;
|
||||
|
||||
#[test]
|
||||
fn pathname_address() {
|
||||
const PATH: &str = "./foo/bar.txt";
|
||||
const PATH_LEN: usize = 13;
|
||||
|
||||
// Pathname addresses do have a null terminator, so `socklen` is
|
||||
// expected to be `PATH_LEN` + `offset` + 1.
|
||||
let path = Path::new(PATH);
|
||||
let (sockaddr, actual) = socket_addr(path).unwrap();
|
||||
let offset = path_offset(&sockaddr);
|
||||
let expected = PATH_LEN + offset + 1;
|
||||
assert_eq!(expected as libc::socklen_t, actual)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn abstract_address() {
|
||||
const PATH: &[u8] = &[0, 116, 111, 107, 105, 111];
|
||||
const PATH_LEN: usize = 6;
|
||||
|
||||
// Abstract addresses do not have a null terminator, so `socklen` is
|
||||
// expected to be `PATH_LEN` + `offset`.
|
||||
let abstract_path = str::from_utf8(PATH).unwrap();
|
||||
let path = Path::new(abstract_path);
|
||||
let (sockaddr, actual) = socket_addr(path).unwrap();
|
||||
let offset = path_offset(&sockaddr);
|
||||
let expected = PATH_LEN + offset;
|
||||
assert_eq!(expected as libc::socklen_t, actual)
|
||||
}
|
||||
// Abstract addresses do not have a null terminator, so `socklen` is
|
||||
// expected to be `PATH_LEN` + `offset`.
|
||||
let address = SocketAddr::from_abstract_name(PATH).unwrap();
|
||||
let (sockaddr, actual) = unix_addr(&address);
|
||||
let offset = path_offset(&sockaddr);
|
||||
let expected = PATH_LEN + offset;
|
||||
assert_eq!(expected as libc::socklen_t, actual)
|
||||
}
|
||||
}
|
||||
|
130
third_party/rust/mio/src/sys/unix/uds/socketaddr.rs
vendored
130
third_party/rust/mio/src/sys/unix/uds/socketaddr.rs
vendored
@ -1,130 +0,0 @@
|
||||
use super::path_offset;
|
||||
use std::ffi::OsStr;
|
||||
use std::os::unix::ffi::OsStrExt;
|
||||
use std::path::Path;
|
||||
use std::{ascii, fmt};
|
||||
|
||||
/// An address associated with a `mio` specific Unix socket.
|
||||
///
|
||||
/// This is implemented instead of imported from [`net::SocketAddr`] because
|
||||
/// there is no way to create a [`net::SocketAddr`]. One must be returned by
|
||||
/// [`accept`], so this is returned instead.
|
||||
///
|
||||
/// [`net::SocketAddr`]: std::os::unix::net::SocketAddr
|
||||
/// [`accept`]: #method.accept
|
||||
pub struct SocketAddr {
|
||||
sockaddr: libc::sockaddr_un,
|
||||
socklen: libc::socklen_t,
|
||||
}
|
||||
|
||||
struct AsciiEscaped<'a>(&'a [u8]);
|
||||
|
||||
enum AddressKind<'a> {
|
||||
Unnamed,
|
||||
Pathname(&'a Path),
|
||||
Abstract(&'a [u8]),
|
||||
}
|
||||
|
||||
impl SocketAddr {
|
||||
fn address(&self) -> AddressKind<'_> {
|
||||
let offset = path_offset(&self.sockaddr);
|
||||
// Don't underflow in `len` below.
|
||||
if (self.socklen as usize) < offset {
|
||||
return AddressKind::Unnamed;
|
||||
}
|
||||
let len = self.socklen as usize - offset;
|
||||
let path = unsafe { &*(&self.sockaddr.sun_path as *const [libc::c_char] as *const [u8]) };
|
||||
|
||||
// macOS seems to return a len of 16 and a zeroed sun_path for unnamed addresses
|
||||
if len == 0
|
||||
|| (cfg!(not(any(target_os = "linux", target_os = "android")))
|
||||
&& self.sockaddr.sun_path[0] == 0)
|
||||
{
|
||||
AddressKind::Unnamed
|
||||
} else if self.sockaddr.sun_path[0] == 0 {
|
||||
AddressKind::Abstract(&path[1..len])
|
||||
} else {
|
||||
AddressKind::Pathname(OsStr::from_bytes(&path[..len - 1]).as_ref())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
cfg_os_poll! {
|
||||
use std::{io, mem};
|
||||
|
||||
impl SocketAddr {
|
||||
pub(crate) fn new<F>(f: F) -> io::Result<SocketAddr>
|
||||
where
|
||||
F: FnOnce(*mut libc::sockaddr, &mut libc::socklen_t) -> io::Result<libc::c_int>,
|
||||
{
|
||||
let mut sockaddr = {
|
||||
let sockaddr = mem::MaybeUninit::<libc::sockaddr_un>::zeroed();
|
||||
unsafe { sockaddr.assume_init() }
|
||||
};
|
||||
|
||||
let raw_sockaddr = &mut sockaddr as *mut libc::sockaddr_un as *mut libc::sockaddr;
|
||||
let mut socklen = mem::size_of_val(&sockaddr) as libc::socklen_t;
|
||||
|
||||
f(raw_sockaddr, &mut socklen)?;
|
||||
Ok(SocketAddr::from_parts(sockaddr, socklen))
|
||||
}
|
||||
|
||||
pub(crate) fn from_parts(sockaddr: libc::sockaddr_un, socklen: libc::socklen_t) -> SocketAddr {
|
||||
SocketAddr { sockaddr, socklen }
|
||||
}
|
||||
|
||||
/// Returns `true` if the address is unnamed.
|
||||
///
|
||||
/// Documentation reflected in [`SocketAddr`]
|
||||
///
|
||||
/// [`SocketAddr`]: std::os::unix::net::SocketAddr
|
||||
pub fn is_unnamed(&self) -> bool {
|
||||
matches!(self.address(), AddressKind::Unnamed)
|
||||
}
|
||||
|
||||
/// Returns the contents of this address if it is a `pathname` address.
|
||||
///
|
||||
/// Documentation reflected in [`SocketAddr`]
|
||||
///
|
||||
/// [`SocketAddr`]: std::os::unix::net::SocketAddr
|
||||
pub fn as_pathname(&self) -> Option<&Path> {
|
||||
if let AddressKind::Pathname(path) = self.address() {
|
||||
Some(path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the contents of this address if it is an abstract namespace
|
||||
/// without the leading null byte.
|
||||
// Link to std::os::unix::net::SocketAddr pending
|
||||
// https://github.com/rust-lang/rust/issues/85410.
|
||||
pub fn as_abstract_namespace(&self) -> Option<&[u8]> {
|
||||
if let AddressKind::Abstract(path) = self.address() {
|
||||
Some(path)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for SocketAddr {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.address() {
|
||||
AddressKind::Unnamed => write!(fmt, "(unnamed)"),
|
||||
AddressKind::Abstract(name) => write!(fmt, "{} (abstract)", AsciiEscaped(name)),
|
||||
AddressKind::Pathname(path) => write!(fmt, "{:?} (pathname)", path),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for AsciiEscaped<'a> {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
write!(fmt, "\"")?;
|
||||
for byte in self.0.iter().cloned().flat_map(ascii::escape_default) {
|
||||
write!(fmt, "{}", byte as char)?;
|
||||
}
|
||||
write!(fmt, "\"")
|
||||
}
|
||||
}
|
27
third_party/rust/mio/src/sys/unix/uds/stream.rs
vendored
27
third_party/rust/mio/src/sys/unix/uds/stream.rs
vendored
@ -1,18 +1,17 @@
|
||||
use super::{socket_addr, SocketAddr};
|
||||
use crate::sys::unix::net::new_socket;
|
||||
|
||||
use std::io;
|
||||
use std::os::unix::io::{AsRawFd, FromRawFd};
|
||||
use std::os::unix::net;
|
||||
use std::path::Path;
|
||||
use std::os::fd::FromRawFd;
|
||||
use std::os::unix::net::{self, SocketAddr};
|
||||
|
||||
pub(crate) fn connect(path: &Path) -> io::Result<net::UnixStream> {
|
||||
let (sockaddr, socklen) = socket_addr(path)?;
|
||||
let sockaddr = &sockaddr as *const libc::sockaddr_un as *const libc::sockaddr;
|
||||
use crate::sys::unix::net::new_socket;
|
||||
use crate::sys::unix::uds::unix_addr;
|
||||
|
||||
pub(crate) fn connect_addr(address: &SocketAddr) -> io::Result<net::UnixStream> {
|
||||
let fd = new_socket(libc::AF_UNIX, libc::SOCK_STREAM)?;
|
||||
let socket = unsafe { net::UnixStream::from_raw_fd(fd) };
|
||||
match syscall!(connect(fd, sockaddr, socklen)) {
|
||||
|
||||
let (unix_address, addrlen) = unix_addr(address);
|
||||
let sockaddr = &unix_address as *const libc::sockaddr_un as *const libc::sockaddr;
|
||||
match syscall!(connect(fd, sockaddr, addrlen)) {
|
||||
Ok(_) => {}
|
||||
Err(ref err) if err.raw_os_error() == Some(libc::EINPROGRESS) => {}
|
||||
Err(e) => return Err(e),
|
||||
@ -24,11 +23,3 @@ pub(crate) fn connect(path: &Path) -> io::Result<net::UnixStream> {
|
||||
pub(crate) fn pair() -> io::Result<(net::UnixStream, net::UnixStream)> {
|
||||
super::pair(libc::SOCK_STREAM)
|
||||
}
|
||||
|
||||
pub(crate) fn local_addr(socket: &net::UnixStream) -> io::Result<SocketAddr> {
|
||||
super::local_addr(socket.as_raw_fd())
|
||||
}
|
||||
|
||||
pub(crate) fn peer_addr(socket: &net::UnixStream) -> io::Result<SocketAddr> {
|
||||
super::peer_addr(socket.as_raw_fd())
|
||||
}
|
||||
|
185
third_party/rust/mio/src/sys/unix/waker.rs
vendored
185
third_party/rust/mio/src/sys/unix/waker.rs
vendored
@ -1,185 +0,0 @@
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
mod eventfd {
|
||||
use crate::sys::Selector;
|
||||
use crate::{Interest, Token};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::os::unix::io::FromRawFd;
|
||||
|
||||
/// Waker backed by `eventfd`.
|
||||
///
|
||||
/// `eventfd` is effectively an 64 bit counter. All writes must be of 8
|
||||
/// bytes (64 bits) and are converted (native endian) into an 64 bit
|
||||
/// unsigned integer and added to the count. Reads must also be 8 bytes and
|
||||
/// reset the count to 0, returning the count.
|
||||
#[derive(Debug)]
|
||||
pub struct Waker {
|
||||
fd: File,
|
||||
}
|
||||
|
||||
impl Waker {
|
||||
pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
|
||||
let fd = syscall!(eventfd(0, libc::EFD_CLOEXEC | libc::EFD_NONBLOCK))?;
|
||||
let file = unsafe { File::from_raw_fd(fd) };
|
||||
|
||||
selector.register(fd, token, Interest::READABLE)?;
|
||||
Ok(Waker { fd: file })
|
||||
}
|
||||
|
||||
pub fn wake(&self) -> io::Result<()> {
|
||||
let buf: [u8; 8] = 1u64.to_ne_bytes();
|
||||
match (&self.fd).write(&buf) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
|
||||
// Writing only blocks if the counter is going to overflow.
|
||||
// So we'll reset the counter to 0 and wake it again.
|
||||
self.reset()?;
|
||||
self.wake()
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
/// Reset the eventfd object, only need to call this if `wake` fails.
|
||||
fn reset(&self) -> io::Result<()> {
|
||||
let mut buf: [u8; 8] = 0u64.to_ne_bytes();
|
||||
match (&self.fd).read(&mut buf) {
|
||||
Ok(_) => Ok(()),
|
||||
// If the `Waker` hasn't been awoken yet this will return a
|
||||
// `WouldBlock` error which we can safely ignore.
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Ok(()),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(target_os = "linux", target_os = "android"))]
|
||||
pub use self::eventfd::Waker;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
mod kqueue {
|
||||
use crate::sys::Selector;
|
||||
use crate::Token;
|
||||
|
||||
use std::io;
|
||||
|
||||
/// Waker backed by kqueue user space notifications (`EVFILT_USER`).
|
||||
///
|
||||
/// The implementation is fairly simple, first the kqueue must be setup to
|
||||
/// receive waker events this done by calling `Selector.setup_waker`. Next
|
||||
/// we need access to kqueue, thus we need to duplicate the file descriptor.
|
||||
/// Now waking is as simple as adding an event to the kqueue.
|
||||
#[derive(Debug)]
|
||||
pub struct Waker {
|
||||
selector: Selector,
|
||||
token: Token,
|
||||
}
|
||||
|
||||
impl Waker {
|
||||
pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
|
||||
let selector = selector.try_clone()?;
|
||||
selector.setup_waker(token)?;
|
||||
Ok(Waker { selector, token })
|
||||
}
|
||||
|
||||
pub fn wake(&self) -> io::Result<()> {
|
||||
self.selector.wake(self.token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "freebsd",
|
||||
target_os = "ios",
|
||||
target_os = "macos",
|
||||
target_os = "tvos",
|
||||
target_os = "watchos",
|
||||
))]
|
||||
pub use self::kqueue::Waker;
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "illumos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
))]
|
||||
mod pipe {
|
||||
use crate::sys::unix::Selector;
|
||||
use crate::{Interest, Token};
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Write};
|
||||
use std::os::unix::io::FromRawFd;
|
||||
|
||||
/// Waker backed by a unix pipe.
|
||||
///
|
||||
/// Waker controls both the sending and receiving ends and empties the pipe
|
||||
/// if writing to it (waking) fails.
|
||||
#[derive(Debug)]
|
||||
pub struct Waker {
|
||||
sender: File,
|
||||
receiver: File,
|
||||
}
|
||||
|
||||
impl Waker {
|
||||
pub fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
|
||||
let mut fds = [-1; 2];
|
||||
syscall!(pipe2(fds.as_mut_ptr(), libc::O_NONBLOCK | libc::O_CLOEXEC))?;
|
||||
let sender = unsafe { File::from_raw_fd(fds[1]) };
|
||||
let receiver = unsafe { File::from_raw_fd(fds[0]) };
|
||||
|
||||
selector.register(fds[0], token, Interest::READABLE)?;
|
||||
Ok(Waker { sender, receiver })
|
||||
}
|
||||
|
||||
pub fn wake(&self) -> io::Result<()> {
|
||||
// The epoll emulation on some illumos systems currently requires
|
||||
// the pipe buffer to be completely empty for an edge-triggered
|
||||
// wakeup on the pipe read side.
|
||||
#[cfg(target_os = "illumos")]
|
||||
self.empty();
|
||||
|
||||
match (&self.sender).write(&[1]) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
|
||||
// The reading end is full so we'll empty the buffer and try
|
||||
// again.
|
||||
self.empty();
|
||||
self.wake()
|
||||
}
|
||||
Err(ref err) if err.kind() == io::ErrorKind::Interrupted => self.wake(),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
/// Empty the pipe's buffer, only need to call this if `wake` fails.
|
||||
/// This ignores any errors.
|
||||
fn empty(&self) {
|
||||
let mut buf = [0; 4096];
|
||||
loop {
|
||||
match (&self.receiver).read(&mut buf) {
|
||||
Ok(n) if n > 0 => continue,
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(
|
||||
target_os = "dragonfly",
|
||||
target_os = "illumos",
|
||||
target_os = "netbsd",
|
||||
target_os = "openbsd",
|
||||
target_os = "redox",
|
||||
))]
|
||||
pub use self::pipe::Waker;
|
81
third_party/rust/mio/src/sys/unix/waker/eventfd.rs
vendored
Normal file
81
third_party/rust/mio/src/sys/unix/waker/eventfd.rs
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Write};
|
||||
#[cfg(not(target_os = "hermit"))]
|
||||
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::{AsRawFd, FromRawFd, RawFd};
|
||||
|
||||
use crate::sys::Selector;
|
||||
use crate::{Interest, Token};
|
||||
|
||||
/// Waker backed by `eventfd`.
|
||||
///
|
||||
/// `eventfd` is effectively an 64 bit counter. All writes must be of 8
|
||||
/// bytes (64 bits) and are converted (native endian) into an 64 bit
|
||||
/// unsigned integer and added to the count. Reads must also be 8 bytes and
|
||||
/// reset the count to 0, returning the count.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Waker {
|
||||
fd: File,
|
||||
}
|
||||
|
||||
impl Waker {
|
||||
#[allow(dead_code)] // Not used by the `poll(2)` implementation.
|
||||
pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
|
||||
let waker = Waker::new_unregistered()?;
|
||||
selector.register(waker.fd.as_raw_fd(), token, Interest::READABLE)?;
|
||||
Ok(waker)
|
||||
}
|
||||
|
||||
pub(crate) fn new_unregistered() -> io::Result<Waker> {
|
||||
#[cfg(not(target_os = "espidf"))]
|
||||
let flags = libc::EFD_CLOEXEC | libc::EFD_NONBLOCK;
|
||||
// ESP-IDF is EFD_NONBLOCK by default and errors if you try to pass this flag.
|
||||
#[cfg(target_os = "espidf")]
|
||||
let flags = 0;
|
||||
let fd = syscall!(eventfd(0, flags))?;
|
||||
let file = unsafe { File::from_raw_fd(fd) };
|
||||
Ok(Waker { fd: file })
|
||||
}
|
||||
|
||||
#[allow(clippy::unused_io_amount)] // Don't care about partial writes.
|
||||
pub(crate) fn wake(&self) -> io::Result<()> {
|
||||
let buf: [u8; 8] = 1u64.to_ne_bytes();
|
||||
match (&self.fd).write(&buf) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
|
||||
// Writing only blocks if the counter is going to overflow.
|
||||
// So we'll reset the counter to 0 and wake it again.
|
||||
self.reset()?;
|
||||
self.wake()
|
||||
}
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // Only used by the `poll(2)` implementation.
|
||||
pub(crate) fn ack_and_reset(&self) {
|
||||
let _ = self.reset();
|
||||
}
|
||||
|
||||
/// Reset the eventfd object, only need to call this if `wake` fails.
|
||||
#[allow(clippy::unused_io_amount)] // Don't care about partial reads.
|
||||
fn reset(&self) -> io::Result<()> {
|
||||
let mut buf: [u8; 8] = 0u64.to_ne_bytes();
|
||||
match (&self.fd).read(&mut buf) {
|
||||
Ok(_) => Ok(()),
|
||||
// If the `Waker` hasn't been awoken yet this will return a
|
||||
// `WouldBlock` error which we can safely ignore.
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => Ok(()),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Waker {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.fd.as_raw_fd()
|
||||
}
|
||||
}
|
28
third_party/rust/mio/src/sys/unix/waker/kqueue.rs
vendored
Normal file
28
third_party/rust/mio/src/sys/unix/waker/kqueue.rs
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
use std::io;
|
||||
|
||||
use crate::sys::Selector;
|
||||
use crate::Token;
|
||||
|
||||
/// Waker backed by kqueue user space notifications (`EVFILT_USER`).
|
||||
///
|
||||
/// The implementation is fairly simple, first the kqueue must be setup to
|
||||
/// receive waker events this done by calling `Selector.setup_waker`. Next
|
||||
/// we need access to kqueue, thus we need to duplicate the file descriptor.
|
||||
/// Now waking is as simple as adding an event to the kqueue.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Waker {
|
||||
selector: Selector,
|
||||
token: Token,
|
||||
}
|
||||
|
||||
impl Waker {
|
||||
pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
|
||||
let selector = selector.try_clone()?;
|
||||
selector.setup_waker(token)?;
|
||||
Ok(Waker { selector, token })
|
||||
}
|
||||
|
||||
pub(crate) fn wake(&self) -> io::Result<()> {
|
||||
self.selector.wake(self.token)
|
||||
}
|
||||
}
|
81
third_party/rust/mio/src/sys/unix/waker/pipe.rs
vendored
Normal file
81
third_party/rust/mio/src/sys/unix/waker/pipe.rs
vendored
Normal file
@ -0,0 +1,81 @@
|
||||
use std::fs::File;
|
||||
use std::io::{self, Read, Write};
|
||||
#[cfg(not(target_os = "hermit"))]
|
||||
use std::os::fd::{AsRawFd, FromRawFd, RawFd};
|
||||
// TODO: once <https://github.com/rust-lang/rust/issues/126198> is fixed this
|
||||
// can use `std::os::fd` and be merged with the above.
|
||||
#[cfg(target_os = "hermit")]
|
||||
use std::os::hermit::io::{AsRawFd, FromRawFd, RawFd};
|
||||
|
||||
use crate::sys::unix::pipe;
|
||||
use crate::sys::Selector;
|
||||
use crate::{Interest, Token};
|
||||
|
||||
/// Waker backed by a unix pipe.
|
||||
///
|
||||
/// Waker controls both the sending and receiving ends and empties the pipe
|
||||
/// if writing to it (waking) fails.
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct Waker {
|
||||
sender: File,
|
||||
receiver: File,
|
||||
}
|
||||
|
||||
impl Waker {
|
||||
#[allow(dead_code)] // Not used by the `poll(2)` implementation.
|
||||
pub(crate) fn new(selector: &Selector, token: Token) -> io::Result<Waker> {
|
||||
let waker = Waker::new_unregistered()?;
|
||||
selector.register(waker.receiver.as_raw_fd(), token, Interest::READABLE)?;
|
||||
Ok(waker)
|
||||
}
|
||||
|
||||
pub(crate) fn new_unregistered() -> io::Result<Waker> {
|
||||
let [receiver, sender] = pipe::new_raw()?;
|
||||
let sender = unsafe { File::from_raw_fd(sender) };
|
||||
let receiver = unsafe { File::from_raw_fd(receiver) };
|
||||
Ok(Waker { sender, receiver })
|
||||
}
|
||||
|
||||
pub(crate) fn wake(&self) -> io::Result<()> {
|
||||
// The epoll emulation on some illumos systems currently requires
|
||||
// the pipe buffer to be completely empty for an edge-triggered
|
||||
// wakeup on the pipe read side.
|
||||
#[cfg(target_os = "illumos")]
|
||||
self.empty();
|
||||
|
||||
match (&self.sender).write(&[1]) {
|
||||
Ok(_) => Ok(()),
|
||||
Err(ref err) if err.kind() == io::ErrorKind::WouldBlock => {
|
||||
// The reading end is full so we'll empty the buffer and try
|
||||
// again.
|
||||
self.empty();
|
||||
self.wake()
|
||||
}
|
||||
Err(ref err) if err.kind() == io::ErrorKind::Interrupted => self.wake(),
|
||||
Err(err) => Err(err),
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)] // Only used by the `poll(2)` implementation.
|
||||
pub(crate) fn ack_and_reset(&self) {
|
||||
self.empty();
|
||||
}
|
||||
|
||||
/// Empty the pipe's buffer, only need to call this if `wake` fails.
|
||||
/// This ignores any errors.
|
||||
fn empty(&self) {
|
||||
let mut buf = [0; 4096];
|
||||
loop {
|
||||
match (&self.receiver).read(&mut buf) {
|
||||
Ok(n) if n > 0 => continue,
|
||||
_ => return,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for Waker {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
self.receiver.as_raw_fd()
|
||||
}
|
||||
}
|
4
third_party/rust/mio/src/sys/wasi/mod.rs
vendored
4
third_party/rust/mio/src/sys/wasi/mod.rs
vendored
@ -207,7 +207,7 @@ impl Selector {
|
||||
}
|
||||
|
||||
/// Token used to a add a timeout subscription, also used in removing it again.
|
||||
const TIMEOUT_TOKEN: wasi::Userdata = wasi::Userdata::max_value();
|
||||
const TIMEOUT_TOKEN: wasi::Userdata = wasi::Userdata::MAX;
|
||||
|
||||
/// Returns a `wasi::Subscription` for `timeout`.
|
||||
fn timeout_subscription(timeout: Duration) -> wasi::Subscription {
|
||||
@ -334,7 +334,7 @@ pub(crate) mod event {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
f.debug_struct("EventFdReadwrite")
|
||||
.field("nbytes", &self.0.nbytes)
|
||||
.field("flags", &self.0.flags)
|
||||
.field("flags", &EventrwflagsDetails(self.0.flags))
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
@ -41,6 +41,14 @@ impl Event {
|
||||
pub(super) fn to_completion_status(&self) -> CompletionStatus {
|
||||
CompletionStatus::new(self.flags, self.data as usize, std::ptr::null_mut())
|
||||
}
|
||||
|
||||
#[cfg(feature = "os-ext")]
|
||||
pub(super) fn to_completion_status_with_overlapped(
|
||||
&self,
|
||||
overlapped: *mut super::Overlapped,
|
||||
) -> CompletionStatus {
|
||||
CompletionStatus::new(self.flags, self.data as usize, overlapped)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) const READABLE_FLAGS: u32 = afd::POLL_RECEIVE
|
||||
|
2
third_party/rust/mio/src/sys/windows/iocp.rs
vendored
2
third_party/rust/mio/src/sys/windows/iocp.rs
vendored
@ -96,7 +96,7 @@ impl CompletionPort {
|
||||
);
|
||||
let mut removed = 0;
|
||||
let timeout = duration_millis(timeout);
|
||||
let len = cmp::min(list.len(), <u32>::max_value() as usize) as u32;
|
||||
let len = cmp::min(list.len(), u32::MAX as usize) as u32;
|
||||
let ret = unsafe {
|
||||
GetQueuedCompletionStatusEx(
|
||||
self.handle.raw(),
|
||||
|
4
third_party/rust/mio/src/sys/windows/mod.rs
vendored
4
third_party/rust/mio/src/sys/windows/mod.rs
vendored
@ -13,7 +13,7 @@ mod overlapped;
|
||||
use overlapped::Overlapped;
|
||||
|
||||
mod selector;
|
||||
pub use selector::{Selector, SelectorInner, SockState};
|
||||
pub use selector::Selector;
|
||||
|
||||
// Macros must be defined before the modules that use them
|
||||
cfg_net! {
|
||||
@ -35,6 +35,8 @@ cfg_net! {
|
||||
|
||||
pub(crate) mod tcp;
|
||||
pub(crate) mod udp;
|
||||
|
||||
pub use selector::{SelectorInner, SockState};
|
||||
}
|
||||
|
||||
cfg_os_ext! {
|
||||
|
@ -84,6 +84,7 @@ struct Inner {
|
||||
connect: Overlapped,
|
||||
read: Overlapped,
|
||||
write: Overlapped,
|
||||
event: Overlapped,
|
||||
// END NOTE.
|
||||
handle: Handle,
|
||||
connecting: AtomicBool,
|
||||
@ -110,10 +111,16 @@ impl Inner {
|
||||
|
||||
/// Same as [`ptr_from_conn_overlapped`] but for `Inner.write`.
|
||||
unsafe fn ptr_from_write_overlapped(ptr: *mut OVERLAPPED) -> *const Inner {
|
||||
// `read` is after `connect: Overlapped` and `read: Overlapped`.
|
||||
// `write` is after `connect: Overlapped` and `read: Overlapped`.
|
||||
(ptr as *mut Overlapped).wrapping_sub(2) as *const Inner
|
||||
}
|
||||
|
||||
/// Same as [`ptr_from_conn_overlapped`] but for `Inner.event`.
|
||||
unsafe fn ptr_from_event_overlapped(ptr: *mut OVERLAPPED) -> *const Inner {
|
||||
// `event` is after `connect: Overlapped`, `read: Overlapped`, and `write: Overlapped`.
|
||||
(ptr as *mut Overlapped).wrapping_sub(3) as *const Inner
|
||||
}
|
||||
|
||||
/// Issue a connection request with the specified overlapped operation.
|
||||
///
|
||||
/// This function will issue a request to connect a client to this server,
|
||||
@ -478,6 +485,7 @@ impl FromRawHandle for NamedPipe {
|
||||
connecting: AtomicBool::new(false),
|
||||
read: Overlapped::new(read_done),
|
||||
write: Overlapped::new(write_done),
|
||||
event: Overlapped::new(event_done),
|
||||
io: Mutex::new(Io {
|
||||
cp: None,
|
||||
token: None,
|
||||
@ -724,7 +732,7 @@ impl Inner {
|
||||
// out the error.
|
||||
Err(e) => {
|
||||
io.read = State::Err(e);
|
||||
io.notify_readable(events);
|
||||
io.notify_readable(me, events);
|
||||
true
|
||||
}
|
||||
}
|
||||
@ -787,7 +795,7 @@ impl Inner {
|
||||
Ok(None) => (),
|
||||
Err(e) => {
|
||||
io.write = State::Err(e);
|
||||
io.notify_writable(events);
|
||||
io.notify_writable(me, events);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -797,7 +805,7 @@ impl Inner {
|
||||
#[allow(clippy::needless_option_as_deref)]
|
||||
if Inner::schedule_read(me, &mut io, events.as_deref_mut()) {
|
||||
if let State::None = io.write {
|
||||
io.notify_writable(events);
|
||||
io.notify_writable(me, events);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -877,7 +885,7 @@ fn read_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
|
||||
}
|
||||
|
||||
// Flag our readiness that we've got data.
|
||||
io.notify_readable(events);
|
||||
io.notify_readable(&me, events);
|
||||
}
|
||||
|
||||
fn write_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
|
||||
@ -895,7 +903,7 @@ fn write_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
|
||||
// `Ok` here means, that the operation was completed immediately
|
||||
// `bytes_transferred` is already reported to a client
|
||||
State::Ok(..) => {
|
||||
io.notify_writable(events);
|
||||
io.notify_writable(&me, events);
|
||||
return;
|
||||
}
|
||||
State::Pending(buf, pos) => (buf, pos),
|
||||
@ -909,7 +917,7 @@ fn write_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
|
||||
let new_pos = pos + (status.bytes_transferred() as usize);
|
||||
if new_pos == buf.len() {
|
||||
me.put_buffer(buf);
|
||||
io.notify_writable(events);
|
||||
io.notify_writable(&me, events);
|
||||
} else {
|
||||
Inner::schedule_write(&me, buf, new_pos, &mut io, events);
|
||||
}
|
||||
@ -917,12 +925,38 @@ fn write_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
|
||||
Err(e) => {
|
||||
debug_assert_eq!(status.bytes_transferred(), 0);
|
||||
io.write = State::Err(e);
|
||||
io.notify_writable(events);
|
||||
io.notify_writable(&me, events);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn event_done(status: &OVERLAPPED_ENTRY, events: Option<&mut Vec<Event>>) {
|
||||
let status = CompletionStatus::from_entry(status);
|
||||
|
||||
// Acquire the `Arc<Inner>`. Note that we should be guaranteed that
|
||||
// the refcount is available to us due to the `mem::forget` in
|
||||
// `schedule_write` above.
|
||||
let me = unsafe { Arc::from_raw(Inner::ptr_from_event_overlapped(status.overlapped())) };
|
||||
|
||||
let io = me.io.lock().unwrap();
|
||||
|
||||
// Make sure the I/O handle is still registered with the selector
|
||||
if io.token.is_some() {
|
||||
// This method is also called during `Selector::drop` to perform
|
||||
// cleanup. In this case, `events` is `None` and we don't need to track
|
||||
// the event.
|
||||
if let Some(events) = events {
|
||||
let mut ev = Event::from_completion_status(&status);
|
||||
// Reverse the `.data` alteration done in `schedule_event`. This
|
||||
// alteration was done so the selector recognized the event as one from
|
||||
// a named pipe.
|
||||
ev.data >>= 1;
|
||||
events.push(ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Io {
|
||||
fn check_association(&self, registry: &Registry, required: bool) -> io::Result<()> {
|
||||
match self.cp {
|
||||
@ -938,7 +972,7 @@ impl Io {
|
||||
}
|
||||
}
|
||||
|
||||
fn notify_readable(&self, events: Option<&mut Vec<Event>>) {
|
||||
fn notify_readable(&self, me: &Arc<Inner>, events: Option<&mut Vec<Event>>) {
|
||||
if let Some(token) = self.token {
|
||||
let mut ev = Event::new(token);
|
||||
ev.set_readable();
|
||||
@ -946,12 +980,12 @@ impl Io {
|
||||
if let Some(events) = events {
|
||||
events.push(ev);
|
||||
} else {
|
||||
let _ = self.cp.as_ref().unwrap().post(ev.to_completion_status());
|
||||
self.schedule_event(me, ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn notify_writable(&self, events: Option<&mut Vec<Event>>) {
|
||||
fn notify_writable(&self, me: &Arc<Inner>, events: Option<&mut Vec<Event>>) {
|
||||
if let Some(token) = self.token {
|
||||
let mut ev = Event::new(token);
|
||||
ev.set_writable();
|
||||
@ -959,7 +993,32 @@ impl Io {
|
||||
if let Some(events) = events {
|
||||
events.push(ev);
|
||||
} else {
|
||||
let _ = self.cp.as_ref().unwrap().post(ev.to_completion_status());
|
||||
self.schedule_event(me, ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn schedule_event(&self, me: &Arc<Inner>, mut event: Event) {
|
||||
// Alter the token so that the selector will identify the IOCP event as
|
||||
// one for a named pipe. This will be reversed in `event_done`
|
||||
//
|
||||
// `data` for named pipes is an auto-incrementing counter. Because
|
||||
// `data` is `u64` we do not risk losing the most-significant bit
|
||||
// (unless a user creates 2^62 named pipes during the lifetime of the
|
||||
// process).
|
||||
event.data <<= 1;
|
||||
event.data += 1;
|
||||
|
||||
let completion_status =
|
||||
event.to_completion_status_with_overlapped(me.event.as_ptr() as *mut _);
|
||||
|
||||
match self.cp.as_ref().unwrap().post(completion_status) {
|
||||
Ok(_) => {
|
||||
// Increase the ref count of `Inner` for the completion event.
|
||||
mem::forget(me.clone());
|
||||
}
|
||||
Err(_) => {
|
||||
// Nothing to do here
|
||||
}
|
||||
}
|
||||
}
|
||||
|
15
third_party/rust/mio/src/sys/windows/selector.rs
vendored
15
third_party/rust/mio/src/sys/windows/selector.rs
vendored
@ -50,7 +50,7 @@ impl AfdGroup {
|
||||
}
|
||||
|
||||
cfg_io_source! {
|
||||
const POLL_GROUP__MAX_GROUP_SIZE: usize = 32;
|
||||
const POLL_GROUP_MAX_GROUP_SIZE: usize = 32;
|
||||
|
||||
impl AfdGroup {
|
||||
pub fn acquire(&self) -> io::Result<Arc<Afd>> {
|
||||
@ -59,7 +59,7 @@ cfg_io_source! {
|
||||
self._alloc_afd_group(&mut afd_group)?;
|
||||
} else {
|
||||
// + 1 reference in Vec
|
||||
if Arc::strong_count(afd_group.last().unwrap()) > POLL_GROUP__MAX_GROUP_SIZE {
|
||||
if Arc::strong_count(afd_group.last().unwrap()) > POLL_GROUP_MAX_GROUP_SIZE {
|
||||
self._alloc_afd_group(&mut afd_group)?;
|
||||
}
|
||||
}
|
||||
@ -328,8 +328,6 @@ pub struct Selector {
|
||||
#[cfg(debug_assertions)]
|
||||
id: usize,
|
||||
pub(super) inner: Arc<SelectorInner>,
|
||||
#[cfg(debug_assertions)]
|
||||
has_waker: AtomicBool,
|
||||
}
|
||||
|
||||
impl Selector {
|
||||
@ -341,8 +339,6 @@ impl Selector {
|
||||
#[cfg(debug_assertions)]
|
||||
id,
|
||||
inner: Arc::new(inner),
|
||||
#[cfg(debug_assertions)]
|
||||
has_waker: AtomicBool::new(false),
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -352,8 +348,6 @@ impl Selector {
|
||||
#[cfg(debug_assertions)]
|
||||
id: self.id,
|
||||
inner: Arc::clone(&self.inner),
|
||||
#[cfg(debug_assertions)]
|
||||
has_waker: AtomicBool::new(self.has_waker.load(Ordering::Acquire)),
|
||||
})
|
||||
}
|
||||
|
||||
@ -365,11 +359,6 @@ impl Selector {
|
||||
self.inner.select(events, timeout)
|
||||
}
|
||||
|
||||
#[cfg(debug_assertions)]
|
||||
pub fn register_waker(&self) -> bool {
|
||||
self.has_waker.swap(true, Ordering::AcqRel)
|
||||
}
|
||||
|
||||
pub(super) fn clone_port(&self) -> Arc<CompletionPort> {
|
||||
self.inner.cp.clone()
|
||||
}
|
||||
|
2
third_party/rust/mio/src/sys/windows/tcp.rs
vendored
2
third_party/rust/mio/src/sys/windows/tcp.rs
vendored
@ -50,7 +50,7 @@ pub(crate) fn listen(socket: &net::TcpListener, backlog: u32) -> io::Result<()>
|
||||
use std::convert::TryInto;
|
||||
use WinSock::listen;
|
||||
|
||||
let backlog = backlog.try_into().unwrap_or(i32::max_value());
|
||||
let backlog = backlog.try_into().unwrap_or(i32::MAX);
|
||||
syscall!(
|
||||
listen(socket.as_raw_socket() as _, backlog),
|
||||
PartialEq::eq,
|
||||
|
@ -1 +1 @@
|
||||
{"files":{"CHANGELOG.md":"0fa977ef55cfe5c26907f5f3c8700a777d205608ab9edf7fd98762b60ba95790","Cargo.toml":"8133ec808652d1d7aa1eb39b135c2afa559265bb46ebbaf2a3cfe8b552fa9202","LICENSE":"9797ea525350e8779aab3771e0276bbeea8b824893882172acfc94743b8d953d","README.md":"6094ea500349ce239a12b07d7dfd4ea965a7f14c993da2abc4b3c39a0479683a","src/entry.rs":"237a4a8e159e841aaa2b49ec1697a68fef6165542ac0197dba1ee963f688dc1d","src/lib.rs":"8ada51fda322e36e6b52a3e1fcbeab7c72332f79e54af111584f5a17b961afb5","src/select.rs":"e01c34fe0fdbc49a40b15b5b42816eea7d7b13db6e3a2774de92eb87f6e48231"},"package":"630bdcf245f78637c13ec01ffae6187cca34625e8c63150d424b59e55af2675e"}
|
||||
{"files":{"CHANGELOG.md":"bc308e94c0a0c9a8c595fdb708dec60d08dca5f4fc67b64287676b619675f91b","Cargo.toml":"b86acb2f048fd43ade67bc01187f9eea2df4855a0261102cca651453a23d5cba","LICENSE":"0b83dc40cba89b9922bb84b0a9c7d2768ce37c1d7e138b7424fd4549915778c9","README.md":"6094ea500349ce239a12b07d7dfd4ea965a7f14c993da2abc4b3c39a0479683a","src/entry.rs":"4b7e392119553a795508aaf021eac5311da50702ac47f536753f8c8e7141593a","src/lib.rs":"b146a3bcf92aaf042e0ff7fd5387b69bc9882d2b5e0ab70298df83ee54ad6d7c","src/select.rs":"8fdef69056b4c24d109439e68535b51c0781505c4b6fc49cacf10d32097c54f1"},"package":"693d596312e88961bc67d7f1f97af8a70227d9f90c31bba5806eec004978d752"}
|
22
third_party/rust/tokio-macros/CHANGELOG.md
vendored
22
third_party/rust/tokio-macros/CHANGELOG.md
vendored
@ -1,3 +1,25 @@
|
||||
# 2.4.0 (July 22nd, 2024)
|
||||
|
||||
- msrv: increase MSRV to 1.70 ([#6645])
|
||||
- macros: allow `unhandled_panic` behavior for `#[tokio::main]` and `#[tokio::test]` ([#6593])
|
||||
|
||||
[#6593]: https://github.com/tokio-rs/tokio/pull/6593
|
||||
[#6645]: https://github.com/tokio-rs/tokio/pull/6645
|
||||
|
||||
# 2.3.0 (May 30th, 2024)
|
||||
|
||||
- macros: make `#[tokio::test]` append `#[test]` at the end of the attribute list ([#6497])
|
||||
|
||||
[#6497]: https://github.com/tokio-rs/tokio/pull/6497
|
||||
|
||||
# 2.2.0 (November 19th, 2023)
|
||||
|
||||
### Changed
|
||||
|
||||
- use `::core` qualified imports instead of `::std` inside `tokio::test` macro ([#5973])
|
||||
|
||||
[#5973]: https://github.com/tokio-rs/tokio/pull/5973
|
||||
|
||||
# 2.1.0 (April 25th, 2023)
|
||||
|
||||
- macros: fix typo in `#[tokio::test]` docs ([#5636])
|
||||
|
8
third_party/rust/tokio-macros/Cargo.toml
vendored
8
third_party/rust/tokio-macros/Cargo.toml
vendored
@ -10,10 +10,10 @@
|
||||
# See Cargo.toml.orig for the original contents.
|
||||
|
||||
[package]
|
||||
edition = "2018"
|
||||
rust-version = "1.56"
|
||||
edition = "2021"
|
||||
rust-version = "1.70"
|
||||
name = "tokio-macros"
|
||||
version = "2.1.0"
|
||||
version = "2.4.0"
|
||||
authors = ["Tokio Contributors <team@tokio.rs>"]
|
||||
description = """
|
||||
Tokio's proc macros.
|
||||
@ -31,7 +31,7 @@ all-features = true
|
||||
proc-macro = true
|
||||
|
||||
[dependencies.proc-macro2]
|
||||
version = "1.0.7"
|
||||
version = "1.0.60"
|
||||
|
||||
[dependencies.quote]
|
||||
version = "1"
|
||||
|
29
third_party/rust/tokio-macros/LICENSE
vendored
29
third_party/rust/tokio-macros/LICENSE
vendored
@ -1,32 +1,7 @@
|
||||
Copyright (c) 2023 Tokio Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
|
||||
The MIT License (MIT)
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 Yoshua Wuyts
|
||||
Copyright (c) Tokio Contributors
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
146
third_party/rust/tokio-macros/src/entry.rs
vendored
146
third_party/rust/tokio-macros/src/entry.rs
vendored
@ -25,11 +25,37 @@ impl RuntimeFlavor {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq)]
|
||||
enum UnhandledPanic {
|
||||
Ignore,
|
||||
ShutdownRuntime,
|
||||
}
|
||||
|
||||
impl UnhandledPanic {
|
||||
fn from_str(s: &str) -> Result<UnhandledPanic, String> {
|
||||
match s {
|
||||
"ignore" => Ok(UnhandledPanic::Ignore),
|
||||
"shutdown_runtime" => Ok(UnhandledPanic::ShutdownRuntime),
|
||||
_ => Err(format!("No such unhandled panic behavior `{}`. The unhandled panic behaviors are `ignore` and `shutdown_runtime`.", s)),
|
||||
}
|
||||
}
|
||||
|
||||
fn into_tokens(self, crate_path: &TokenStream) -> TokenStream {
|
||||
match self {
|
||||
UnhandledPanic::Ignore => quote! { #crate_path::runtime::UnhandledPanic::Ignore },
|
||||
UnhandledPanic::ShutdownRuntime => {
|
||||
quote! { #crate_path::runtime::UnhandledPanic::ShutdownRuntime }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct FinalConfig {
|
||||
flavor: RuntimeFlavor,
|
||||
worker_threads: Option<usize>,
|
||||
start_paused: Option<bool>,
|
||||
crate_name: Option<Path>,
|
||||
unhandled_panic: Option<UnhandledPanic>,
|
||||
}
|
||||
|
||||
/// Config used in case of the attribute not being able to build a valid config
|
||||
@ -38,6 +64,7 @@ const DEFAULT_ERROR_CONFIG: FinalConfig = FinalConfig {
|
||||
worker_threads: None,
|
||||
start_paused: None,
|
||||
crate_name: None,
|
||||
unhandled_panic: None,
|
||||
};
|
||||
|
||||
struct Configuration {
|
||||
@ -48,6 +75,7 @@ struct Configuration {
|
||||
start_paused: Option<(bool, Span)>,
|
||||
is_test: bool,
|
||||
crate_name: Option<Path>,
|
||||
unhandled_panic: Option<(UnhandledPanic, Span)>,
|
||||
}
|
||||
|
||||
impl Configuration {
|
||||
@ -63,6 +91,7 @@ impl Configuration {
|
||||
start_paused: None,
|
||||
is_test,
|
||||
crate_name: None,
|
||||
unhandled_panic: None,
|
||||
}
|
||||
}
|
||||
|
||||
@ -117,6 +146,25 @@ impl Configuration {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn set_unhandled_panic(
|
||||
&mut self,
|
||||
unhandled_panic: syn::Lit,
|
||||
span: Span,
|
||||
) -> Result<(), syn::Error> {
|
||||
if self.unhandled_panic.is_some() {
|
||||
return Err(syn::Error::new(
|
||||
span,
|
||||
"`unhandled_panic` set multiple times.",
|
||||
));
|
||||
}
|
||||
|
||||
let unhandled_panic = parse_string(unhandled_panic, span, "unhandled_panic")?;
|
||||
let unhandled_panic =
|
||||
UnhandledPanic::from_str(&unhandled_panic).map_err(|err| syn::Error::new(span, err))?;
|
||||
self.unhandled_panic = Some((unhandled_panic, span));
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn macro_name(&self) -> &'static str {
|
||||
if self.is_test {
|
||||
"tokio::test"
|
||||
@ -126,22 +174,22 @@ impl Configuration {
|
||||
}
|
||||
|
||||
fn build(&self) -> Result<FinalConfig, syn::Error> {
|
||||
let flavor = self.flavor.unwrap_or(self.default_flavor);
|
||||
use RuntimeFlavor::*;
|
||||
use RuntimeFlavor as F;
|
||||
|
||||
let flavor = self.flavor.unwrap_or(self.default_flavor);
|
||||
let worker_threads = match (flavor, self.worker_threads) {
|
||||
(CurrentThread, Some((_, worker_threads_span))) => {
|
||||
(F::CurrentThread, Some((_, worker_threads_span))) => {
|
||||
let msg = format!(
|
||||
"The `worker_threads` option requires the `multi_thread` runtime flavor. Use `#[{}(flavor = \"multi_thread\")]`",
|
||||
self.macro_name(),
|
||||
);
|
||||
return Err(syn::Error::new(worker_threads_span, msg));
|
||||
}
|
||||
(CurrentThread, None) => None,
|
||||
(Threaded, worker_threads) if self.rt_multi_thread_available => {
|
||||
(F::CurrentThread, None) => None,
|
||||
(F::Threaded, worker_threads) if self.rt_multi_thread_available => {
|
||||
worker_threads.map(|(val, _span)| val)
|
||||
}
|
||||
(Threaded, _) => {
|
||||
(F::Threaded, _) => {
|
||||
let msg = if self.flavor.is_none() {
|
||||
"The default runtime flavor is `multi_thread`, but the `rt-multi-thread` feature is disabled."
|
||||
} else {
|
||||
@ -152,14 +200,26 @@ impl Configuration {
|
||||
};
|
||||
|
||||
let start_paused = match (flavor, self.start_paused) {
|
||||
(Threaded, Some((_, start_paused_span))) => {
|
||||
(F::Threaded, Some((_, start_paused_span))) => {
|
||||
let msg = format!(
|
||||
"The `start_paused` option requires the `current_thread` runtime flavor. Use `#[{}(flavor = \"current_thread\")]`",
|
||||
self.macro_name(),
|
||||
);
|
||||
return Err(syn::Error::new(start_paused_span, msg));
|
||||
}
|
||||
(CurrentThread, Some((start_paused, _))) => Some(start_paused),
|
||||
(F::CurrentThread, Some((start_paused, _))) => Some(start_paused),
|
||||
(_, None) => None,
|
||||
};
|
||||
|
||||
let unhandled_panic = match (flavor, self.unhandled_panic) {
|
||||
(F::Threaded, Some((_, unhandled_panic_span))) => {
|
||||
let msg = format!(
|
||||
"The `unhandled_panic` option requires the `current_thread` runtime flavor. Use `#[{}(flavor = \"current_thread\")]`",
|
||||
self.macro_name(),
|
||||
);
|
||||
return Err(syn::Error::new(unhandled_panic_span, msg));
|
||||
}
|
||||
(F::CurrentThread, Some((unhandled_panic, _))) => Some(unhandled_panic),
|
||||
(_, None) => None,
|
||||
};
|
||||
|
||||
@ -168,6 +228,7 @@ impl Configuration {
|
||||
flavor,
|
||||
worker_threads,
|
||||
start_paused,
|
||||
unhandled_panic,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -275,9 +336,13 @@ fn build_config(
|
||||
"crate" => {
|
||||
config.set_crate_name(lit.clone(), syn::spanned::Spanned::span(lit))?;
|
||||
}
|
||||
"unhandled_panic" => {
|
||||
config
|
||||
.set_unhandled_panic(lit.clone(), syn::spanned::Spanned::span(lit))?;
|
||||
}
|
||||
name => {
|
||||
let msg = format!(
|
||||
"Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`",
|
||||
"Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`, `unhandled_panic`",
|
||||
name,
|
||||
);
|
||||
return Err(syn::Error::new_spanned(namevalue, msg));
|
||||
@ -303,11 +368,11 @@ fn build_config(
|
||||
macro_name
|
||||
)
|
||||
}
|
||||
"flavor" | "worker_threads" | "start_paused" => {
|
||||
"flavor" | "worker_threads" | "start_paused" | "crate" | "unhandled_panic" => {
|
||||
format!("The `{}` attribute requires an argument.", name)
|
||||
}
|
||||
name => {
|
||||
format!("Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`", name)
|
||||
format!("Unknown attribute {} is specified; expected one of: `flavor`, `worker_threads`, `start_paused`, `crate`, `unhandled_panic`.", name)
|
||||
}
|
||||
};
|
||||
return Err(syn::Error::new_spanned(path, msg));
|
||||
@ -354,13 +419,17 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt
|
||||
},
|
||||
};
|
||||
if let Some(v) = config.worker_threads {
|
||||
rt = quote! { #rt.worker_threads(#v) };
|
||||
rt = quote_spanned! {last_stmt_start_span=> #rt.worker_threads(#v) };
|
||||
}
|
||||
if let Some(v) = config.start_paused {
|
||||
rt = quote! { #rt.start_paused(#v) };
|
||||
rt = quote_spanned! {last_stmt_start_span=> #rt.start_paused(#v) };
|
||||
}
|
||||
if let Some(v) = config.unhandled_panic {
|
||||
let unhandled_panic = v.into_tokens(&crate_path);
|
||||
rt = quote_spanned! {last_stmt_start_span=> #rt.unhandled_panic(#unhandled_panic) };
|
||||
}
|
||||
|
||||
let header = if is_test {
|
||||
let generated_attrs = if is_test {
|
||||
quote! {
|
||||
#[::core::prelude::v1::test]
|
||||
}
|
||||
@ -402,7 +471,7 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt
|
||||
quote! {
|
||||
let body = async #body;
|
||||
#crate_path::pin!(body);
|
||||
let body: ::std::pin::Pin<&mut dyn ::std::future::Future<Output = #output_type>> = body;
|
||||
let body: ::core::pin::Pin<&mut dyn ::core::future::Future<Output = #output_type>> = body;
|
||||
}
|
||||
} else {
|
||||
quote! {
|
||||
@ -410,7 +479,7 @@ fn parse_knobs(mut input: ItemFn, is_test: bool, config: FinalConfig) -> TokenSt
|
||||
}
|
||||
};
|
||||
|
||||
input.into_tokens(header, body, last_block)
|
||||
input.into_tokens(generated_attrs, body, last_block)
|
||||
}
|
||||
|
||||
fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenStream {
|
||||
@ -418,7 +487,6 @@ fn token_stream_with_error(mut tokens: TokenStream, error: syn::Error) -> TokenS
|
||||
tokens
|
||||
}
|
||||
|
||||
#[cfg(not(test))] // Work around for rust-lang/rust#62127
|
||||
pub(crate) fn main(args: TokenStream, item: TokenStream, rt_multi_thread: bool) -> TokenStream {
|
||||
// If any of the steps for this macro fail, we still want to expand to an item that is as close
|
||||
// to the expected output as possible. This helps out IDEs such that completions and other
|
||||
@ -443,6 +511,35 @@ pub(crate) fn main(args: TokenStream, item: TokenStream, rt_multi_thread: bool)
|
||||
}
|
||||
}
|
||||
|
||||
// Check whether given attribute is a test attribute of forms:
|
||||
// * `#[test]`
|
||||
// * `#[core::prelude::*::test]` or `#[::core::prelude::*::test]`
|
||||
// * `#[std::prelude::*::test]` or `#[::std::prelude::*::test]`
|
||||
fn is_test_attribute(attr: &Attribute) -> bool {
|
||||
let path = match &attr.meta {
|
||||
syn::Meta::Path(path) => path,
|
||||
_ => return false,
|
||||
};
|
||||
let candidates = [
|
||||
["core", "prelude", "*", "test"],
|
||||
["std", "prelude", "*", "test"],
|
||||
];
|
||||
if path.leading_colon.is_none()
|
||||
&& path.segments.len() == 1
|
||||
&& path.segments[0].arguments.is_none()
|
||||
&& path.segments[0].ident == "test"
|
||||
{
|
||||
return true;
|
||||
} else if path.segments.len() != candidates[0].len() {
|
||||
return false;
|
||||
}
|
||||
candidates.into_iter().any(|segments| {
|
||||
path.segments.iter().zip(segments).all(|(segment, path)| {
|
||||
segment.arguments.is_none() && (path == "*" || segment.ident == path)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn test(args: TokenStream, item: TokenStream, rt_multi_thread: bool) -> TokenStream {
|
||||
// If any of the steps for this macro fail, we still want to expand to an item that is as close
|
||||
// to the expected output as possible. This helps out IDEs such that completions and other
|
||||
@ -451,8 +548,8 @@ pub(crate) fn test(args: TokenStream, item: TokenStream, rt_multi_thread: bool)
|
||||
Ok(it) => it,
|
||||
Err(e) => return token_stream_with_error(item, e),
|
||||
};
|
||||
let config = if let Some(attr) = input.attrs().find(|attr| attr.meta.path().is_ident("test")) {
|
||||
let msg = "second test attribute is supplied";
|
||||
let config = if let Some(attr) = input.attrs().find(|attr| is_test_attribute(attr)) {
|
||||
let msg = "second test attribute is supplied, consider removing or changing the order of your test attributes";
|
||||
Err(syn::Error::new_spanned(attr, msg))
|
||||
} else {
|
||||
AttributeArgs::parse_terminated
|
||||
@ -493,13 +590,11 @@ impl ItemFn {
|
||||
/// Convert our local function item into a token stream.
|
||||
fn into_tokens(
|
||||
self,
|
||||
header: proc_macro2::TokenStream,
|
||||
generated_attrs: proc_macro2::TokenStream,
|
||||
body: proc_macro2::TokenStream,
|
||||
last_block: proc_macro2::TokenStream,
|
||||
) -> TokenStream {
|
||||
let mut tokens = proc_macro2::TokenStream::new();
|
||||
header.to_tokens(&mut tokens);
|
||||
|
||||
// Outer attributes are simply streamed as-is.
|
||||
for attr in self.outer_attrs {
|
||||
attr.to_tokens(&mut tokens);
|
||||
@ -507,12 +602,15 @@ impl ItemFn {
|
||||
|
||||
// Inner attributes require extra care, since they're not supported on
|
||||
// blocks (which is what we're expanded into) we instead lift them
|
||||
// outside of the function. This matches the behaviour of `syn`.
|
||||
// outside of the function. This matches the behavior of `syn`.
|
||||
for mut attr in self.inner_attrs {
|
||||
attr.style = syn::AttrStyle::Outer;
|
||||
attr.to_tokens(&mut tokens);
|
||||
}
|
||||
|
||||
// Add generated macros at the end, so macros processed later are aware of them.
|
||||
generated_attrs.to_tokens(&mut tokens);
|
||||
|
||||
self.vis.to_tokens(&mut tokens);
|
||||
self.sig.to_tokens(&mut tokens);
|
||||
|
||||
@ -586,6 +684,6 @@ impl ToTokens for Body<'_> {
|
||||
for stmt in self.stmts {
|
||||
stmt.to_tokens(tokens);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
100
third_party/rust/tokio-macros/src/lib.rs
vendored
100
third_party/rust/tokio-macros/src/lib.rs
vendored
@ -1,3 +1,4 @@
|
||||
#![allow(unknown_lints, unexpected_cfgs)]
|
||||
#![allow(clippy::needless_doctest_main)]
|
||||
#![warn(
|
||||
missing_debug_implementations,
|
||||
@ -201,15 +202,60 @@ use proc_macro::TokenStream;
|
||||
/// })
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ### Configure unhandled panic behavior
|
||||
///
|
||||
/// Available options are `shutdown_runtime` and `ignore`. For more details, see
|
||||
/// [`Builder::unhandled_panic`].
|
||||
///
|
||||
/// This option is only compatible with the `current_thread` runtime.
|
||||
///
|
||||
/// ```no_run
|
||||
/// #[cfg(tokio_unstable)]
|
||||
/// #[tokio::main(flavor = "current_thread", unhandled_panic = "shutdown_runtime")]
|
||||
/// async fn main() {
|
||||
/// let _ = tokio::spawn(async {
|
||||
/// panic!("This panic will shutdown the runtime.");
|
||||
/// }).await;
|
||||
/// }
|
||||
/// # #[cfg(not(tokio_unstable))]
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
///
|
||||
/// Equivalent code not using `#[tokio::main]`
|
||||
///
|
||||
/// ```no_run
|
||||
/// #[cfg(tokio_unstable)]
|
||||
/// fn main() {
|
||||
/// tokio::runtime::Builder::new_current_thread()
|
||||
/// .enable_all()
|
||||
/// .unhandled_panic(UnhandledPanic::ShutdownRuntime)
|
||||
/// .build()
|
||||
/// .unwrap()
|
||||
/// .block_on(async {
|
||||
/// let _ = tokio::spawn(async {
|
||||
/// panic!("This panic will shutdown the runtime.");
|
||||
/// }).await;
|
||||
/// })
|
||||
/// }
|
||||
/// # #[cfg(not(tokio_unstable))]
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
///
|
||||
/// **Note**: This option depends on Tokio's [unstable API][unstable]. See [the
|
||||
/// documentation on unstable features][unstable] for details on how to enable
|
||||
/// Tokio's unstable features.
|
||||
///
|
||||
/// [`Builder::unhandled_panic`]: ../tokio/runtime/struct.Builder.html#method.unhandled_panic
|
||||
/// [unstable]: ../tokio/index.html#unstable-features
|
||||
#[proc_macro_attribute]
|
||||
#[cfg(not(test))] // Work around for rust-lang/rust#62127
|
||||
pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
entry::main(args.into(), item.into(), true).into()
|
||||
}
|
||||
|
||||
/// Marks async function to be executed by selected runtime. This macro helps set up a `Runtime`
|
||||
/// without requiring the user to use [Runtime](../tokio/runtime/struct.Runtime.html) or
|
||||
/// [Builder](../tokio/runtime/struct.builder.html) directly.
|
||||
/// [Builder](../tokio/runtime/struct.Builder.html) directly.
|
||||
///
|
||||
/// ## Function arguments:
|
||||
///
|
||||
@ -267,7 +313,6 @@ pub fn main(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
/// }
|
||||
/// ```
|
||||
#[proc_macro_attribute]
|
||||
#[cfg(not(test))] // Work around for rust-lang/rust#62127
|
||||
pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
entry::main(args.into(), item.into(), false).into()
|
||||
}
|
||||
@ -365,7 +410,7 @@ pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
/// ### Set number of worker threads
|
||||
///
|
||||
/// ```no_run
|
||||
/// #[tokio::test(flavor ="multi_thread", worker_threads = 2)]
|
||||
/// #[tokio::test(flavor = "multi_thread", worker_threads = 2)]
|
||||
/// async fn my_test() {
|
||||
/// assert!(true);
|
||||
/// }
|
||||
@ -424,6 +469,53 @@ pub fn main_rt(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
/// println!("Hello world");
|
||||
/// }
|
||||
/// ```
|
||||
///
|
||||
/// ### Configure unhandled panic behavior
|
||||
///
|
||||
/// Available options are `shutdown_runtime` and `ignore`. For more details, see
|
||||
/// [`Builder::unhandled_panic`].
|
||||
///
|
||||
/// This option is only compatible with the `current_thread` runtime.
|
||||
///
|
||||
/// ```no_run
|
||||
/// #[cfg(tokio_unstable)]
|
||||
/// #[tokio::test(flavor = "current_thread", unhandled_panic = "shutdown_runtime")]
|
||||
/// async fn my_test() {
|
||||
/// let _ = tokio::spawn(async {
|
||||
/// panic!("This panic will shutdown the runtime.");
|
||||
/// }).await;
|
||||
/// }
|
||||
/// # #[cfg(not(tokio_unstable))]
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
///
|
||||
/// Equivalent code not using `#[tokio::test]`
|
||||
///
|
||||
/// ```no_run
|
||||
/// #[cfg(tokio_unstable)]
|
||||
/// #[test]
|
||||
/// fn my_test() {
|
||||
/// tokio::runtime::Builder::new_current_thread()
|
||||
/// .enable_all()
|
||||
/// .unhandled_panic(UnhandledPanic::ShutdownRuntime)
|
||||
/// .build()
|
||||
/// .unwrap()
|
||||
/// .block_on(async {
|
||||
/// let _ = tokio::spawn(async {
|
||||
/// panic!("This panic will shutdown the runtime.");
|
||||
/// }).await;
|
||||
/// })
|
||||
/// }
|
||||
/// # #[cfg(not(tokio_unstable))]
|
||||
/// # fn main() { }
|
||||
/// ```
|
||||
///
|
||||
/// **Note**: This option depends on Tokio's [unstable API][unstable]. See [the
|
||||
/// documentation on unstable features][unstable] for details on how to enable
|
||||
/// Tokio's unstable features.
|
||||
///
|
||||
/// [`Builder::unhandled_panic`]: ../tokio/runtime/struct.Builder.html#method.unhandled_panic
|
||||
/// [unstable]: ../tokio/index.html#unstable-features
|
||||
#[proc_macro_attribute]
|
||||
pub fn test(args: TokenStream, item: TokenStream) -> TokenStream {
|
||||
entry::test(args.into(), item.into(), true).into()
|
||||
|
10
third_party/rust/tokio-macros/src/select.rs
vendored
10
third_party/rust/tokio-macros/src/select.rs
vendored
@ -73,27 +73,27 @@ fn clean_pattern(pat: &mut syn::Pat) {
|
||||
}
|
||||
}
|
||||
syn::Pat::Or(or) => {
|
||||
for case in or.cases.iter_mut() {
|
||||
for case in &mut or.cases {
|
||||
clean_pattern(case);
|
||||
}
|
||||
}
|
||||
syn::Pat::Slice(slice) => {
|
||||
for elem in slice.elems.iter_mut() {
|
||||
for elem in &mut slice.elems {
|
||||
clean_pattern(elem);
|
||||
}
|
||||
}
|
||||
syn::Pat::Struct(struct_pat) => {
|
||||
for field in struct_pat.fields.iter_mut() {
|
||||
for field in &mut struct_pat.fields {
|
||||
clean_pattern(&mut field.pat);
|
||||
}
|
||||
}
|
||||
syn::Pat::Tuple(tuple) => {
|
||||
for elem in tuple.elems.iter_mut() {
|
||||
for elem in &mut tuple.elems {
|
||||
clean_pattern(elem);
|
||||
}
|
||||
}
|
||||
syn::Pat::TupleStruct(tuple) => {
|
||||
for elem in tuple.elems.iter_mut() {
|
||||
for elem in &mut tuple.elems {
|
||||
clean_pattern(elem);
|
||||
}
|
||||
}
|
||||
|
2
third_party/rust/tokio/.cargo-checksum.json
vendored
2
third_party/rust/tokio/.cargo-checksum.json
vendored
File diff suppressed because one or more lines are too long
632
third_party/rust/tokio/CHANGELOG.md
vendored
632
third_party/rust/tokio/CHANGELOG.md
vendored
@ -1,3 +1,598 @@
|
||||
# 1.39.2 (July 27th, 2024)
|
||||
|
||||
This release fixes a regression where the `select!` macro stopped accepting
|
||||
expressions that make use of temporary lifetime extension. ([#6722])
|
||||
|
||||
[#6722]: https://github.com/tokio-rs/tokio/pull/6722
|
||||
|
||||
# 1.39.1 (July 23rd, 2024)
|
||||
|
||||
This release reverts "time: avoid traversing entries in the time wheel twice"
|
||||
because it contains a bug. ([#6715])
|
||||
|
||||
[#6715]: https://github.com/tokio-rs/tokio/pull/6715
|
||||
|
||||
# 1.39.0 (July 23rd, 2024)
|
||||
|
||||
Yanked. Please use 1.39.1 instead.
|
||||
|
||||
- This release bumps the MSRV to 1.70. ([#6645])
|
||||
- This release upgrades to mio v1. ([#6635])
|
||||
- This release upgrades to windows-sys v0.52 ([#6154])
|
||||
|
||||
### Added
|
||||
|
||||
- io: implement `AsyncSeek` for `Empty` ([#6663])
|
||||
- metrics: stabilize `num_alive_tasks` ([#6619], [#6667])
|
||||
- process: add `Command::as_std_mut` ([#6608])
|
||||
- sync: add `watch::Sender::same_channel` ([#6637])
|
||||
- sync: add `{Receiver,UnboundedReceiver}::{sender_strong_count,sender_weak_count}` ([#6661])
|
||||
- sync: implement `Default` for `watch::Sender` ([#6626])
|
||||
- task: implement `Clone` for `AbortHandle` ([#6621])
|
||||
- task: stabilize `consume_budget` ([#6622])
|
||||
|
||||
### Changed
|
||||
|
||||
- io: improve panic message of `ReadBuf::put_slice()` ([#6629])
|
||||
- io: read during write in `copy_bidirectional` and `copy` ([#6532])
|
||||
- runtime: replace `num_cpus` with `available_parallelism` ([#6709])
|
||||
- task: avoid stack overflow when passing large future to `block_on` ([#6692])
|
||||
- time: avoid traversing entries in the time wheel twice ([#6584])
|
||||
- time: support `IntoFuture` with `timeout` ([#6666])
|
||||
- macros: support `IntoFuture` with `join!` and `select!` ([#6710])
|
||||
|
||||
### Fixed
|
||||
|
||||
- docs: fix docsrs builds with the fs feature enabled ([#6585])
|
||||
- io: only use short-read optimization on known-to-be-compatible platforms ([#6668])
|
||||
- time: fix overflow panic when using large durations with `Interval` ([#6612])
|
||||
|
||||
### Added (unstable)
|
||||
|
||||
- macros: allow `unhandled_panic` behavior for `#[tokio::main]` and `#[tokio::test]` ([#6593])
|
||||
- metrics: add `spawned_tasks_count` ([#6114])
|
||||
- metrics: add `worker_park_unpark_count` ([#6696])
|
||||
- metrics: add worker thread id ([#6695])
|
||||
|
||||
### Documented
|
||||
|
||||
- io: update `tokio::io::stdout` documentation ([#6674])
|
||||
- macros: typo fix in `join.rs` and `try_join.rs` ([#6641])
|
||||
- runtime: fix typo in `unhandled_panic` ([#6660])
|
||||
- task: document behavior of `JoinSet::try_join_next` when all tasks are running ([#6671])
|
||||
|
||||
[#6114]: https://github.com/tokio-rs/tokio/pull/6114
|
||||
[#6154]: https://github.com/tokio-rs/tokio/pull/6154
|
||||
[#6532]: https://github.com/tokio-rs/tokio/pull/6532
|
||||
[#6584]: https://github.com/tokio-rs/tokio/pull/6584
|
||||
[#6585]: https://github.com/tokio-rs/tokio/pull/6585
|
||||
[#6593]: https://github.com/tokio-rs/tokio/pull/6593
|
||||
[#6608]: https://github.com/tokio-rs/tokio/pull/6608
|
||||
[#6612]: https://github.com/tokio-rs/tokio/pull/6612
|
||||
[#6619]: https://github.com/tokio-rs/tokio/pull/6619
|
||||
[#6621]: https://github.com/tokio-rs/tokio/pull/6621
|
||||
[#6622]: https://github.com/tokio-rs/tokio/pull/6622
|
||||
[#6626]: https://github.com/tokio-rs/tokio/pull/6626
|
||||
[#6629]: https://github.com/tokio-rs/tokio/pull/6629
|
||||
[#6635]: https://github.com/tokio-rs/tokio/pull/6635
|
||||
[#6637]: https://github.com/tokio-rs/tokio/pull/6637
|
||||
[#6641]: https://github.com/tokio-rs/tokio/pull/6641
|
||||
[#6645]: https://github.com/tokio-rs/tokio/pull/6645
|
||||
[#6660]: https://github.com/tokio-rs/tokio/pull/6660
|
||||
[#6661]: https://github.com/tokio-rs/tokio/pull/6661
|
||||
[#6663]: https://github.com/tokio-rs/tokio/pull/6663
|
||||
[#6666]: https://github.com/tokio-rs/tokio/pull/6666
|
||||
[#6667]: https://github.com/tokio-rs/tokio/pull/6667
|
||||
[#6668]: https://github.com/tokio-rs/tokio/pull/6668
|
||||
[#6671]: https://github.com/tokio-rs/tokio/pull/6671
|
||||
[#6674]: https://github.com/tokio-rs/tokio/pull/6674
|
||||
[#6692]: https://github.com/tokio-rs/tokio/pull/6692
|
||||
[#6695]: https://github.com/tokio-rs/tokio/pull/6695
|
||||
[#6696]: https://github.com/tokio-rs/tokio/pull/6696
|
||||
[#6709]: https://github.com/tokio-rs/tokio/pull/6709
|
||||
[#6710]: https://github.com/tokio-rs/tokio/pull/6710
|
||||
|
||||
# 1.38.1 (July 16th, 2024)
|
||||
|
||||
This release fixes the bug identified as ([#6682]), which caused timers not
|
||||
to fire when they should.
|
||||
|
||||
### Fixed
|
||||
|
||||
- time: update `wake_up` while holding all the locks of sharded time wheels ([#6683])
|
||||
|
||||
[#6682]: https://github.com/tokio-rs/tokio/pull/6682
|
||||
[#6683]: https://github.com/tokio-rs/tokio/pull/6683
|
||||
|
||||
# 1.38.0 (May 30th, 2024)
|
||||
|
||||
This release marks the beginning of stabilization for runtime metrics. It
|
||||
stabilizes `RuntimeMetrics::worker_count`. Future releases will continue to
|
||||
stabilize more metrics.
|
||||
|
||||
### Added
|
||||
|
||||
- fs: add `File::create_new` ([#6573])
|
||||
- io: add `copy_bidirectional_with_sizes` ([#6500])
|
||||
- io: implement `AsyncBufRead` for `Join` ([#6449])
|
||||
- net: add Apple visionOS support ([#6465])
|
||||
- net: implement `Clone` for `NamedPipeInfo` ([#6586])
|
||||
- net: support QNX OS ([#6421])
|
||||
- sync: add `Notify::notify_last` ([#6520])
|
||||
- sync: add `mpsc::Receiver::{capacity,max_capacity}` ([#6511])
|
||||
- sync: add `split` method to the semaphore permit ([#6472], [#6478])
|
||||
- task: add `tokio::task::join_set::Builder::spawn_blocking` ([#6578])
|
||||
- wasm: support rt-multi-thread with wasm32-wasi-preview1-threads ([#6510])
|
||||
|
||||
### Changed
|
||||
|
||||
- macros: make `#[tokio::test]` append `#[test]` at the end of the attribute list ([#6497])
|
||||
- metrics: fix `blocking_threads` count ([#6551])
|
||||
- metrics: stabilize `RuntimeMetrics::worker_count` ([#6556])
|
||||
- runtime: move task out of the `lifo_slot` in `block_in_place` ([#6596])
|
||||
- runtime: panic if `global_queue_interval` is zero ([#6445])
|
||||
- sync: always drop message in destructor for oneshot receiver ([#6558])
|
||||
- sync: instrument `Semaphore` for task dumps ([#6499])
|
||||
- sync: use FIFO ordering when waking batches of wakers ([#6521])
|
||||
- task: make `LocalKey::get` work with Clone types ([#6433])
|
||||
- tests: update nix and mio-aio dev-dependencies ([#6552])
|
||||
- time: clean up implementation ([#6517])
|
||||
- time: lazily init timers on first poll ([#6512])
|
||||
- time: remove the `true_when` field in `TimerShared` ([#6563])
|
||||
- time: use sharding for timer implementation ([#6534])
|
||||
|
||||
### Fixed
|
||||
|
||||
- taskdump: allow building taskdump docs on non-unix machines ([#6564])
|
||||
- time: check for overflow in `Interval::poll_tick` ([#6487])
|
||||
- sync: fix incorrect `is_empty` on mpsc block boundaries ([#6603])
|
||||
|
||||
### Documented
|
||||
|
||||
- fs: rewrite file system docs ([#6467])
|
||||
- io: fix `stdin` documentation ([#6581])
|
||||
- io: fix obsolete reference in `ReadHalf::unsplit()` documentation ([#6498])
|
||||
- macros: render more comprehensible documentation for `select!` ([#6468])
|
||||
- net: add missing types to module docs ([#6482])
|
||||
- net: fix misleading `NamedPipeServer` example ([#6590])
|
||||
- sync: add examples for `SemaphorePermit`, `OwnedSemaphorePermit` ([#6477])
|
||||
- sync: document that `Barrier::wait` is not cancel safe ([#6494])
|
||||
- sync: explain relation between `watch::Sender::{subscribe,closed}` ([#6490])
|
||||
- task: clarify that you can't abort `spawn_blocking` tasks ([#6571])
|
||||
- task: fix a typo in doc of `LocalSet::run_until` ([#6599])
|
||||
- time: fix test-util requirement for pause and resume in docs ([#6503])
|
||||
|
||||
[#6421]: https://github.com/tokio-rs/tokio/pull/6421
|
||||
[#6433]: https://github.com/tokio-rs/tokio/pull/6433
|
||||
[#6445]: https://github.com/tokio-rs/tokio/pull/6445
|
||||
[#6449]: https://github.com/tokio-rs/tokio/pull/6449
|
||||
[#6465]: https://github.com/tokio-rs/tokio/pull/6465
|
||||
[#6467]: https://github.com/tokio-rs/tokio/pull/6467
|
||||
[#6468]: https://github.com/tokio-rs/tokio/pull/6468
|
||||
[#6472]: https://github.com/tokio-rs/tokio/pull/6472
|
||||
[#6477]: https://github.com/tokio-rs/tokio/pull/6477
|
||||
[#6478]: https://github.com/tokio-rs/tokio/pull/6478
|
||||
[#6482]: https://github.com/tokio-rs/tokio/pull/6482
|
||||
[#6487]: https://github.com/tokio-rs/tokio/pull/6487
|
||||
[#6490]: https://github.com/tokio-rs/tokio/pull/6490
|
||||
[#6494]: https://github.com/tokio-rs/tokio/pull/6494
|
||||
[#6497]: https://github.com/tokio-rs/tokio/pull/6497
|
||||
[#6498]: https://github.com/tokio-rs/tokio/pull/6498
|
||||
[#6499]: https://github.com/tokio-rs/tokio/pull/6499
|
||||
[#6500]: https://github.com/tokio-rs/tokio/pull/6500
|
||||
[#6503]: https://github.com/tokio-rs/tokio/pull/6503
|
||||
[#6510]: https://github.com/tokio-rs/tokio/pull/6510
|
||||
[#6511]: https://github.com/tokio-rs/tokio/pull/6511
|
||||
[#6512]: https://github.com/tokio-rs/tokio/pull/6512
|
||||
[#6517]: https://github.com/tokio-rs/tokio/pull/6517
|
||||
[#6520]: https://github.com/tokio-rs/tokio/pull/6520
|
||||
[#6521]: https://github.com/tokio-rs/tokio/pull/6521
|
||||
[#6534]: https://github.com/tokio-rs/tokio/pull/6534
|
||||
[#6551]: https://github.com/tokio-rs/tokio/pull/6551
|
||||
[#6552]: https://github.com/tokio-rs/tokio/pull/6552
|
||||
[#6556]: https://github.com/tokio-rs/tokio/pull/6556
|
||||
[#6558]: https://github.com/tokio-rs/tokio/pull/6558
|
||||
[#6563]: https://github.com/tokio-rs/tokio/pull/6563
|
||||
[#6564]: https://github.com/tokio-rs/tokio/pull/6564
|
||||
[#6571]: https://github.com/tokio-rs/tokio/pull/6571
|
||||
[#6573]: https://github.com/tokio-rs/tokio/pull/6573
|
||||
[#6578]: https://github.com/tokio-rs/tokio/pull/6578
|
||||
[#6581]: https://github.com/tokio-rs/tokio/pull/6581
|
||||
[#6586]: https://github.com/tokio-rs/tokio/pull/6586
|
||||
[#6590]: https://github.com/tokio-rs/tokio/pull/6590
|
||||
[#6596]: https://github.com/tokio-rs/tokio/pull/6596
|
||||
[#6599]: https://github.com/tokio-rs/tokio/pull/6599
|
||||
[#6603]: https://github.com/tokio-rs/tokio/pull/6603
|
||||
|
||||
# 1.37.0 (March 28th, 2024)
|
||||
|
||||
### Added
|
||||
|
||||
- fs: add `set_max_buf_size` to `tokio::fs::File` ([#6411])
|
||||
- io: add `try_new` and `try_with_interest` to `AsyncFd` ([#6345])
|
||||
- sync: add `forget_permits` method to semaphore ([#6331])
|
||||
- sync: add `is_closed`, `is_empty`, and `len` to mpsc receivers ([#6348])
|
||||
- sync: add a `rwlock()` method to owned `RwLock` guards ([#6418])
|
||||
- sync: expose strong and weak counts of mpsc sender handles ([#6405])
|
||||
- sync: implement `Clone` for `watch::Sender` ([#6388])
|
||||
- task: add `TaskLocalFuture::take_value` ([#6340])
|
||||
- task: implement `FromIterator` for `JoinSet` ([#6300])
|
||||
|
||||
### Changed
|
||||
|
||||
- io: make `io::split` use a mutex instead of a spinlock ([#6403])
|
||||
|
||||
### Fixed
|
||||
|
||||
- docs: fix docsrs build without net feature ([#6360])
|
||||
- macros: allow select with only else branch ([#6339])
|
||||
- runtime: fix leaking registration entries when os registration fails ([#6329])
|
||||
|
||||
### Documented
|
||||
|
||||
- io: document cancel safety of `AsyncBufReadExt::fill_buf` ([#6431])
|
||||
- io: document cancel safety of `AsyncReadExt`'s primitive read functions ([#6337])
|
||||
- runtime: add doc link from `Runtime` to `#[tokio::main]` ([#6366])
|
||||
- runtime: make the `enter` example deterministic ([#6351])
|
||||
- sync: add Semaphore example for limiting the number of outgoing requests ([#6419])
|
||||
- sync: fix missing period in broadcast docs ([#6377])
|
||||
- sync: mark `mpsc::Sender::downgrade` with `#[must_use]` ([#6326])
|
||||
- sync: reorder `const_new` before `new_with` ([#6392])
|
||||
- sync: update watch channel docs ([#6395])
|
||||
- task: fix documentation links ([#6336])
|
||||
|
||||
### Changed (unstable)
|
||||
|
||||
- runtime: include task `Id` in taskdumps ([#6328])
|
||||
- runtime: panic if `unhandled_panic` is enabled when not supported ([#6410])
|
||||
|
||||
[#6300]: https://github.com/tokio-rs/tokio/pull/6300
|
||||
[#6326]: https://github.com/tokio-rs/tokio/pull/6326
|
||||
[#6328]: https://github.com/tokio-rs/tokio/pull/6328
|
||||
[#6329]: https://github.com/tokio-rs/tokio/pull/6329
|
||||
[#6331]: https://github.com/tokio-rs/tokio/pull/6331
|
||||
[#6336]: https://github.com/tokio-rs/tokio/pull/6336
|
||||
[#6337]: https://github.com/tokio-rs/tokio/pull/6337
|
||||
[#6339]: https://github.com/tokio-rs/tokio/pull/6339
|
||||
[#6340]: https://github.com/tokio-rs/tokio/pull/6340
|
||||
[#6345]: https://github.com/tokio-rs/tokio/pull/6345
|
||||
[#6348]: https://github.com/tokio-rs/tokio/pull/6348
|
||||
[#6351]: https://github.com/tokio-rs/tokio/pull/6351
|
||||
[#6360]: https://github.com/tokio-rs/tokio/pull/6360
|
||||
[#6366]: https://github.com/tokio-rs/tokio/pull/6366
|
||||
[#6377]: https://github.com/tokio-rs/tokio/pull/6377
|
||||
[#6388]: https://github.com/tokio-rs/tokio/pull/6388
|
||||
[#6392]: https://github.com/tokio-rs/tokio/pull/6392
|
||||
[#6395]: https://github.com/tokio-rs/tokio/pull/6395
|
||||
[#6403]: https://github.com/tokio-rs/tokio/pull/6403
|
||||
[#6405]: https://github.com/tokio-rs/tokio/pull/6405
|
||||
[#6410]: https://github.com/tokio-rs/tokio/pull/6410
|
||||
[#6411]: https://github.com/tokio-rs/tokio/pull/6411
|
||||
[#6418]: https://github.com/tokio-rs/tokio/pull/6418
|
||||
[#6419]: https://github.com/tokio-rs/tokio/pull/6419
|
||||
[#6431]: https://github.com/tokio-rs/tokio/pull/6431
|
||||
|
||||
# 1.36.0 (February 2nd, 2024)
|
||||
|
||||
### Added
|
||||
|
||||
- io: add `tokio::io::Join` ([#6220])
|
||||
- io: implement `AsyncWrite` for `Empty` ([#6235])
|
||||
- net: add support for anonymous unix pipes ([#6127])
|
||||
- net: add `UnixSocket` ([#6290])
|
||||
- net: expose keepalive option on `TcpSocket` ([#6311])
|
||||
- sync: add `{Receiver,UnboundedReceiver}::poll_recv_many` ([#6236])
|
||||
- sync: add `Sender::{try_,}reserve_many` ([#6205])
|
||||
- sync: add `watch::Receiver::mark_unchanged` ([#6252])
|
||||
- task: add `JoinSet::try_join_next` ([#6280])
|
||||
|
||||
### Changed
|
||||
|
||||
- io: make `copy` cooperative ([#6265])
|
||||
- io: make `repeat` and `sink` cooperative ([#6254])
|
||||
- io: simplify check for empty slice ([#6293])
|
||||
- process: use pidfd on Linux when available ([#6152])
|
||||
- sync: use AtomicBool in broadcast channel future ([#6298])
|
||||
|
||||
### Documented
|
||||
|
||||
- io: clarify `clear_ready` docs ([#6304])
|
||||
- net: document that `*Fd` traits on `TcpSocket` are unix-only ([#6294])
|
||||
- sync: document FIFO behavior of `tokio::sync::Mutex` ([#6279])
|
||||
- chore: typographic improvements ([#6262])
|
||||
- runtime: remove obsolete comment ([#6303])
|
||||
- task: fix typo ([#6261])
|
||||
|
||||
[#6220]: https://github.com/tokio-rs/tokio/pull/6220
|
||||
[#6235]: https://github.com/tokio-rs/tokio/pull/6235
|
||||
[#6127]: https://github.com/tokio-rs/tokio/pull/6127
|
||||
[#6290]: https://github.com/tokio-rs/tokio/pull/6290
|
||||
[#6311]: https://github.com/tokio-rs/tokio/pull/6311
|
||||
[#6236]: https://github.com/tokio-rs/tokio/pull/6236
|
||||
[#6205]: https://github.com/tokio-rs/tokio/pull/6205
|
||||
[#6252]: https://github.com/tokio-rs/tokio/pull/6252
|
||||
[#6280]: https://github.com/tokio-rs/tokio/pull/6280
|
||||
[#6265]: https://github.com/tokio-rs/tokio/pull/6265
|
||||
[#6254]: https://github.com/tokio-rs/tokio/pull/6254
|
||||
[#6293]: https://github.com/tokio-rs/tokio/pull/6293
|
||||
[#6238]: https://github.com/tokio-rs/tokio/pull/6238
|
||||
[#6152]: https://github.com/tokio-rs/tokio/pull/6152
|
||||
[#6298]: https://github.com/tokio-rs/tokio/pull/6298
|
||||
[#6262]: https://github.com/tokio-rs/tokio/pull/6262
|
||||
[#6303]: https://github.com/tokio-rs/tokio/pull/6303
|
||||
[#6261]: https://github.com/tokio-rs/tokio/pull/6261
|
||||
[#6304]: https://github.com/tokio-rs/tokio/pull/6304
|
||||
[#6294]: https://github.com/tokio-rs/tokio/pull/6294
|
||||
[#6279]: https://github.com/tokio-rs/tokio/pull/6279
|
||||
|
||||
# 1.35.1 (December 19, 2023)
|
||||
|
||||
This is a forward part of a change that was backported to 1.25.3.
|
||||
|
||||
### Fixed
|
||||
|
||||
- io: add budgeting to `tokio::runtime::io::registration::async_io` ([#6221])
|
||||
|
||||
[#6221]: https://github.com/tokio-rs/tokio/pull/6221
|
||||
|
||||
# 1.35.0 (December 8th, 2023)
|
||||
|
||||
### Added
|
||||
|
||||
- net: add Apple watchOS support ([#6176])
|
||||
|
||||
### Changed
|
||||
|
||||
- io: drop the `Sized` requirements from `AsyncReadExt.read_buf` ([#6169])
|
||||
- runtime: make `Runtime` unwind safe ([#6189])
|
||||
- runtime: reduce the lock contention in task spawn ([#6001])
|
||||
- tokio: update nix dependency to 0.27.1 ([#6190])
|
||||
|
||||
### Fixed
|
||||
|
||||
- chore: make `--cfg docsrs` work without net feature ([#6166])
|
||||
- chore: use relaxed load for `unsync_load` on miri ([#6179])
|
||||
- runtime: handle missing context on wake ([#6148])
|
||||
- taskdump: fix taskdump cargo config example ([#6150])
|
||||
- taskdump: skip notified tasks during taskdumps ([#6194])
|
||||
- tracing: avoid creating resource spans with current parent, use a None parent instead ([#6107])
|
||||
- tracing: make task span explicit root ([#6158])
|
||||
|
||||
### Documented
|
||||
|
||||
- io: flush in `AsyncWriteExt` examples ([#6149])
|
||||
- runtime: document fairness guarantees and current behavior ([#6145])
|
||||
- task: document cancel safety of `LocalSet::run_until` ([#6147])
|
||||
|
||||
[#6001]: https://github.com/tokio-rs/tokio/pull/6001
|
||||
[#6107]: https://github.com/tokio-rs/tokio/pull/6107
|
||||
[#6144]: https://github.com/tokio-rs/tokio/pull/6144
|
||||
[#6145]: https://github.com/tokio-rs/tokio/pull/6145
|
||||
[#6147]: https://github.com/tokio-rs/tokio/pull/6147
|
||||
[#6148]: https://github.com/tokio-rs/tokio/pull/6148
|
||||
[#6149]: https://github.com/tokio-rs/tokio/pull/6149
|
||||
[#6150]: https://github.com/tokio-rs/tokio/pull/6150
|
||||
[#6158]: https://github.com/tokio-rs/tokio/pull/6158
|
||||
[#6166]: https://github.com/tokio-rs/tokio/pull/6166
|
||||
[#6169]: https://github.com/tokio-rs/tokio/pull/6169
|
||||
[#6176]: https://github.com/tokio-rs/tokio/pull/6176
|
||||
[#6179]: https://github.com/tokio-rs/tokio/pull/6179
|
||||
[#6189]: https://github.com/tokio-rs/tokio/pull/6189
|
||||
[#6190]: https://github.com/tokio-rs/tokio/pull/6190
|
||||
[#6194]: https://github.com/tokio-rs/tokio/pull/6194
|
||||
|
||||
# 1.34.0 (November 19th, 2023)
|
||||
|
||||
### Fixed
|
||||
|
||||
- io: allow `clear_readiness` after io driver shutdown ([#6067])
|
||||
- io: fix integer overflow in `take` ([#6080])
|
||||
- io: fix I/O resource hang ([#6134])
|
||||
- sync: fix `broadcast::channel` link ([#6100])
|
||||
|
||||
### Changed
|
||||
|
||||
- macros: use `::core` qualified imports instead of `::std` inside `tokio::test` macro ([#5973])
|
||||
|
||||
### Added
|
||||
|
||||
- fs: update cfg attr in `fs::read_dir` to include `aix` ([#6075])
|
||||
- sync: add `mpsc::Receiver::recv_many` ([#6010])
|
||||
- tokio: added vita target support ([#6094])
|
||||
|
||||
[#5973]: https://github.com/tokio-rs/tokio/pull/5973
|
||||
[#6067]: https://github.com/tokio-rs/tokio/pull/6067
|
||||
[#6080]: https://github.com/tokio-rs/tokio/pull/6080
|
||||
[#6134]: https://github.com/tokio-rs/tokio/pull/6134
|
||||
[#6100]: https://github.com/tokio-rs/tokio/pull/6100
|
||||
[#6075]: https://github.com/tokio-rs/tokio/pull/6075
|
||||
[#6010]: https://github.com/tokio-rs/tokio/pull/6010
|
||||
[#6094]: https://github.com/tokio-rs/tokio/pull/6094
|
||||
|
||||
# 1.33.0 (October 9, 2023)
|
||||
|
||||
### Fixed
|
||||
|
||||
- io: mark `Interest::add` with `#[must_use]` ([#6037])
|
||||
- runtime: fix cache line size for RISC-V ([#5994])
|
||||
- sync: prevent lock poisoning in `watch::Receiver::wait_for` ([#6021])
|
||||
- task: fix `spawn_local` source location ([#5984])
|
||||
|
||||
### Changed
|
||||
|
||||
- sync: use Acquire/Release orderings instead of SeqCst in `watch` ([#6018])
|
||||
|
||||
### Added
|
||||
|
||||
- fs: add vectored writes to `tokio::fs::File` ([#5958])
|
||||
- io: add `Interest::remove` method ([#5906])
|
||||
- io: add vectored writes to `DuplexStream` ([#5985])
|
||||
- net: add Apple tvOS support ([#6045])
|
||||
- sync: add `?Sized` bound to `{MutexGuard,OwnedMutexGuard}::map` ([#5997])
|
||||
- sync: add `watch::Receiver::mark_unseen` ([#5962], [#6014], [#6017])
|
||||
- sync: add `watch::Sender::new` ([#5998])
|
||||
- sync: add const fn `OnceCell::from_value` ([#5903])
|
||||
|
||||
### Removed
|
||||
|
||||
- remove unused `stats` feature ([#5952])
|
||||
|
||||
### Documented
|
||||
|
||||
- add missing backticks in code examples ([#5938], [#6056])
|
||||
- fix typos ([#5988], [#6030])
|
||||
- process: document that `Child::wait` is cancel safe ([#5977])
|
||||
- sync: add examples for `Semaphore` ([#5939], [#5956], [#5978], [#6031], [#6032], [#6050])
|
||||
- sync: document that `broadcast` capacity is a lower bound ([#6042])
|
||||
- sync: document that `const_new` is not instrumented ([#6002])
|
||||
- sync: improve cancel-safety documentation for `mpsc::Sender::send` ([#5947])
|
||||
- sync: improve docs for `watch` channel ([#5954])
|
||||
- taskdump: render taskdump documentation on docs.rs ([#5972])
|
||||
|
||||
### Unstable
|
||||
|
||||
- taskdump: fix potential deadlock ([#6036])
|
||||
|
||||
[#5903]: https://github.com/tokio-rs/tokio/pull/5903
|
||||
[#5906]: https://github.com/tokio-rs/tokio/pull/5906
|
||||
[#5938]: https://github.com/tokio-rs/tokio/pull/5938
|
||||
[#5939]: https://github.com/tokio-rs/tokio/pull/5939
|
||||
[#5947]: https://github.com/tokio-rs/tokio/pull/5947
|
||||
[#5952]: https://github.com/tokio-rs/tokio/pull/5952
|
||||
[#5954]: https://github.com/tokio-rs/tokio/pull/5954
|
||||
[#5956]: https://github.com/tokio-rs/tokio/pull/5956
|
||||
[#5958]: https://github.com/tokio-rs/tokio/pull/5958
|
||||
[#5960]: https://github.com/tokio-rs/tokio/pull/5960
|
||||
[#5962]: https://github.com/tokio-rs/tokio/pull/5962
|
||||
[#5971]: https://github.com/tokio-rs/tokio/pull/5971
|
||||
[#5972]: https://github.com/tokio-rs/tokio/pull/5972
|
||||
[#5977]: https://github.com/tokio-rs/tokio/pull/5977
|
||||
[#5978]: https://github.com/tokio-rs/tokio/pull/5978
|
||||
[#5984]: https://github.com/tokio-rs/tokio/pull/5984
|
||||
[#5985]: https://github.com/tokio-rs/tokio/pull/5985
|
||||
[#5988]: https://github.com/tokio-rs/tokio/pull/5988
|
||||
[#5994]: https://github.com/tokio-rs/tokio/pull/5994
|
||||
[#5997]: https://github.com/tokio-rs/tokio/pull/5997
|
||||
[#5998]: https://github.com/tokio-rs/tokio/pull/5998
|
||||
[#6002]: https://github.com/tokio-rs/tokio/pull/6002
|
||||
[#6014]: https://github.com/tokio-rs/tokio/pull/6014
|
||||
[#6017]: https://github.com/tokio-rs/tokio/pull/6017
|
||||
[#6018]: https://github.com/tokio-rs/tokio/pull/6018
|
||||
[#6021]: https://github.com/tokio-rs/tokio/pull/6021
|
||||
[#6030]: https://github.com/tokio-rs/tokio/pull/6030
|
||||
[#6031]: https://github.com/tokio-rs/tokio/pull/6031
|
||||
[#6032]: https://github.com/tokio-rs/tokio/pull/6032
|
||||
[#6036]: https://github.com/tokio-rs/tokio/pull/6036
|
||||
[#6037]: https://github.com/tokio-rs/tokio/pull/6037
|
||||
[#6042]: https://github.com/tokio-rs/tokio/pull/6042
|
||||
[#6045]: https://github.com/tokio-rs/tokio/pull/6045
|
||||
[#6050]: https://github.com/tokio-rs/tokio/pull/6050
|
||||
[#6056]: https://github.com/tokio-rs/tokio/pull/6056
|
||||
[#6058]: https://github.com/tokio-rs/tokio/pull/6058
|
||||
|
||||
# 1.32.1 (December 19, 2023)
|
||||
|
||||
This is a forward part of a change that was backported to 1.25.3.
|
||||
|
||||
### Fixed
|
||||
|
||||
- io: add budgeting to `tokio::runtime::io::registration::async_io` ([#6221])
|
||||
|
||||
[#6221]: https://github.com/tokio-rs/tokio/pull/6221
|
||||
|
||||
# 1.32.0 (August 16, 2023)
|
||||
|
||||
### Fixed
|
||||
|
||||
- sync: fix potential quadratic behavior in `broadcast::Receiver` ([#5925])
|
||||
|
||||
### Added
|
||||
|
||||
- process: stabilize `Command::raw_arg` ([#5930])
|
||||
- io: enable awaiting error readiness ([#5781])
|
||||
|
||||
### Unstable
|
||||
|
||||
- rt(alt): improve scalability of alt runtime as the number of cores grows ([#5935])
|
||||
|
||||
[#5925]: https://github.com/tokio-rs/tokio/pull/5925
|
||||
[#5930]: https://github.com/tokio-rs/tokio/pull/5930
|
||||
[#5781]: https://github.com/tokio-rs/tokio/pull/5781
|
||||
[#5935]: https://github.com/tokio-rs/tokio/pull/5935
|
||||
|
||||
# 1.31.0 (August 10, 2023)
|
||||
|
||||
### Fixed
|
||||
|
||||
* io: delegate `WriteHalf::poll_write_vectored` ([#5914])
|
||||
|
||||
### Unstable
|
||||
|
||||
* rt(alt): fix memory leak in unstable next-gen scheduler prototype ([#5911])
|
||||
* rt: expose mean task poll time metric ([#5927])
|
||||
|
||||
[#5914]: https://github.com/tokio-rs/tokio/pull/5914
|
||||
[#5911]: https://github.com/tokio-rs/tokio/pull/5911
|
||||
[#5927]: https://github.com/tokio-rs/tokio/pull/5927
|
||||
|
||||
# 1.30.0 (August 9, 2023)
|
||||
|
||||
This release bumps the MSRV of Tokio to 1.63. ([#5887])
|
||||
|
||||
### Changed
|
||||
|
||||
- tokio: reduce LLVM code generation ([#5859])
|
||||
- io: support `--cfg mio_unsupported_force_poll_poll` flag ([#5881])
|
||||
- sync: make `const_new` methods always available ([#5885])
|
||||
- sync: avoid false sharing in mpsc channel ([#5829])
|
||||
- rt: pop at least one task from inject queue ([#5908])
|
||||
|
||||
### Added
|
||||
|
||||
- sync: add `broadcast::Sender::new` ([#5824])
|
||||
- net: implement `UCred` for espidf ([#5868])
|
||||
- fs: add `File::options()` ([#5869])
|
||||
- time: implement extra reset variants for `Interval` ([#5878])
|
||||
- process: add `{ChildStd*}::into_owned_{fd, handle}` ([#5899])
|
||||
|
||||
### Removed
|
||||
|
||||
- tokio: removed unused `tokio_*` cfgs ([#5890])
|
||||
- remove build script to speed up compilation ([#5887])
|
||||
|
||||
### Documented
|
||||
|
||||
- sync: mention lagging in docs for `broadcast::send` ([#5820])
|
||||
- runtime: expand on sharing runtime docs ([#5858])
|
||||
- io: use vec in example for `AsyncReadExt::read_exact` ([#5863])
|
||||
- time: mark `Sleep` as `!Unpin` in docs ([#5916])
|
||||
- process: fix `raw_arg` not showing up in docs ([#5865])
|
||||
|
||||
### Unstable
|
||||
|
||||
- rt: add runtime ID ([#5864])
|
||||
- rt: initial implementation of new threaded runtime ([#5823])
|
||||
|
||||
[#5820]: https://github.com/tokio-rs/tokio/pull/5820
|
||||
[#5823]: https://github.com/tokio-rs/tokio/pull/5823
|
||||
[#5824]: https://github.com/tokio-rs/tokio/pull/5824
|
||||
[#5829]: https://github.com/tokio-rs/tokio/pull/5829
|
||||
[#5858]: https://github.com/tokio-rs/tokio/pull/5858
|
||||
[#5859]: https://github.com/tokio-rs/tokio/pull/5859
|
||||
[#5863]: https://github.com/tokio-rs/tokio/pull/5863
|
||||
[#5864]: https://github.com/tokio-rs/tokio/pull/5864
|
||||
[#5865]: https://github.com/tokio-rs/tokio/pull/5865
|
||||
[#5868]: https://github.com/tokio-rs/tokio/pull/5868
|
||||
[#5869]: https://github.com/tokio-rs/tokio/pull/5869
|
||||
[#5878]: https://github.com/tokio-rs/tokio/pull/5878
|
||||
[#5881]: https://github.com/tokio-rs/tokio/pull/5881
|
||||
[#5885]: https://github.com/tokio-rs/tokio/pull/5885
|
||||
[#5887]: https://github.com/tokio-rs/tokio/pull/5887
|
||||
[#5890]: https://github.com/tokio-rs/tokio/pull/5890
|
||||
[#5899]: https://github.com/tokio-rs/tokio/pull/5899
|
||||
[#5908]: https://github.com/tokio-rs/tokio/pull/5908
|
||||
[#5916]: https://github.com/tokio-rs/tokio/pull/5916
|
||||
|
||||
# 1.29.1 (June 29, 2023)
|
||||
|
||||
### Fixed
|
||||
@ -267,6 +862,23 @@ This release bumps the MSRV of Tokio to 1.56. ([#5559])
|
||||
[#5513]: https://github.com/tokio-rs/tokio/pull/5513
|
||||
[#5517]: https://github.com/tokio-rs/tokio/pull/5517
|
||||
|
||||
# 1.25.3 (December 17th, 2023)
|
||||
|
||||
### Fixed
|
||||
- io: add budgeting to `tokio::runtime::io::registration::async_io` ([#6221])
|
||||
|
||||
[#6221]: https://github.com/tokio-rs/tokio/pull/6221
|
||||
|
||||
# 1.25.2 (September 22, 2023)
|
||||
|
||||
Forward ports 1.20.6 changes.
|
||||
|
||||
### Changed
|
||||
|
||||
- io: use `memchr` from `libc` ([#5960])
|
||||
|
||||
[#5960]: https://github.com/tokio-rs/tokio/pull/5960
|
||||
|
||||
# 1.25.1 (May 28, 2023)
|
||||
|
||||
Forward ports 1.18.6 changes.
|
||||
@ -613,6 +1225,16 @@ wasm32-wasi target is given unstable support for the `net` feature.
|
||||
[#4956]: https://github.com/tokio-rs/tokio/pull/4956
|
||||
[#4959]: https://github.com/tokio-rs/tokio/pull/4959
|
||||
|
||||
# 1.20.6 (September 22, 2023)
|
||||
|
||||
This is a backport of a change from 1.27.0.
|
||||
|
||||
### Changed
|
||||
|
||||
- io: use `memchr` from `libc` ([#5960])
|
||||
|
||||
[#5960]: https://github.com/tokio-rs/tokio/pull/5960
|
||||
|
||||
# 1.20.5 (May 28, 2023)
|
||||
|
||||
Forward ports 1.18.6 changes.
|
||||
@ -1325,7 +1947,9 @@ Fixes a missed edge case from 1.8.1.
|
||||
|
||||
### Fixed
|
||||
|
||||
- runtime: drop canceled future on next poll (#3965)
|
||||
- runtime: drop canceled future on next poll ([#3965])
|
||||
|
||||
[#3965]: https://github.com/tokio-rs/tokio/pull/3965
|
||||
|
||||
# 1.8.1 (July 6, 2021)
|
||||
|
||||
@ -1346,7 +1970,7 @@ Forward ports 1.5.1 fixes.
|
||||
- net: add ready/try methods to `NamedPipe{Client,Server}` ([#3866], [#3899])
|
||||
- sync: add `watch::Receiver::borrow_and_update` ([#3813])
|
||||
- sync: implement `From<T>` for `OnceCell<T>` ([#3877])
|
||||
- time: allow users to specify Interval behaviour when delayed ([#3721])
|
||||
- time: allow users to specify Interval behavior when delayed ([#3721])
|
||||
|
||||
### Added (unstable)
|
||||
|
||||
@ -1360,7 +1984,7 @@ Forward ports 1.5.1 fixes.
|
||||
|
||||
- doc: document cancellation safety ([#3900])
|
||||
- time: add wait alias to sleep ([#3897])
|
||||
- time: document auto-advancing behaviour of runtime ([#3763])
|
||||
- time: document auto-advancing behavior of runtime ([#3763])
|
||||
|
||||
[#3163]: https://github.com/tokio-rs/tokio/pull/3163
|
||||
[#3721]: https://github.com/tokio-rs/tokio/pull/3721
|
||||
@ -1607,7 +2231,7 @@ a kernel bug. ([#3803])
|
||||
|
||||
- doc: doc aliases for pre-1.0 function names ([#3523])
|
||||
- io: fix typos ([#3541])
|
||||
- io: note the EOF behaviour of `read_until` ([#3536])
|
||||
- io: note the EOF behavior of `read_until` ([#3536])
|
||||
- io: update `AsyncRead::poll_read` doc ([#3557])
|
||||
- net: update `UdpSocket` splitting doc ([#3517])
|
||||
- runtime: add link to `LocalSet` on `new_current_thread` ([#3508])
|
||||
|
63
third_party/rust/tokio/Cargo.toml
vendored
63
third_party/rust/tokio/Cargo.toml
vendored
@ -11,9 +11,9 @@
|
||||
|
||||
[package]
|
||||
edition = "2021"
|
||||
rust-version = "1.56"
|
||||
rust-version = "1.70"
|
||||
name = "tokio"
|
||||
version = "1.29.1"
|
||||
version = "1.39.2"
|
||||
authors = ["Tokio Contributors <team@tokio.rs>"]
|
||||
description = """
|
||||
An event-driven, non-blocking I/O platform for writing asynchronous I/O
|
||||
@ -34,17 +34,28 @@ categories = [
|
||||
license = "MIT"
|
||||
repository = "https://github.com/tokio-rs/tokio"
|
||||
|
||||
[package.metadata.cargo_check_external_types]
|
||||
allowed_external_types = [
|
||||
"bytes::buf::buf_impl::Buf",
|
||||
"bytes::buf::buf_mut::BufMut",
|
||||
"tokio_macros::*",
|
||||
]
|
||||
|
||||
[package.metadata.docs.rs]
|
||||
all-features = true
|
||||
rustc-args = [
|
||||
"--cfg",
|
||||
"tokio_unstable",
|
||||
"--cfg",
|
||||
"tokio_taskdump",
|
||||
]
|
||||
rustdoc-args = [
|
||||
"--cfg",
|
||||
"docsrs",
|
||||
"--cfg",
|
||||
"tokio_unstable",
|
||||
"--cfg",
|
||||
"tokio_taskdump",
|
||||
]
|
||||
|
||||
[package.metadata.playground]
|
||||
@ -58,23 +69,19 @@ version = "1.0.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.mio]
|
||||
version = "0.8.6"
|
||||
version = "1.0.1"
|
||||
optional = true
|
||||
default-features = false
|
||||
|
||||
[dependencies.num_cpus]
|
||||
version = "1.8.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.parking_lot]
|
||||
version = "0.12.0"
|
||||
optional = true
|
||||
|
||||
[dependencies.pin-project-lite]
|
||||
version = "0.2.7"
|
||||
version = "0.2.11"
|
||||
|
||||
[dependencies.tokio-macros]
|
||||
version = "~2.1.0"
|
||||
version = "~2.4.0"
|
||||
optional = true
|
||||
|
||||
[dev-dependencies.async-stream]
|
||||
@ -93,9 +100,6 @@ version = "0.1"
|
||||
[dev-dependencies.tokio-test]
|
||||
version = "0.4.0"
|
||||
|
||||
[build-dependencies.autocfg]
|
||||
version = "1.1"
|
||||
|
||||
[features]
|
||||
default = []
|
||||
fs = []
|
||||
@ -140,10 +144,7 @@ process = [
|
||||
"windows-sys/Win32_System_WindowsProgramming",
|
||||
]
|
||||
rt = []
|
||||
rt-multi-thread = [
|
||||
"num_cpus",
|
||||
"rt",
|
||||
]
|
||||
rt-multi-thread = ["rt"]
|
||||
signal = [
|
||||
"libc",
|
||||
"mio/os-poll",
|
||||
@ -153,7 +154,6 @@ signal = [
|
||||
"windows-sys/Win32_Foundation",
|
||||
"windows-sys/Win32_System_Console",
|
||||
]
|
||||
stats = []
|
||||
sync = []
|
||||
test-util = [
|
||||
"rt",
|
||||
@ -162,32 +162,32 @@ test-util = [
|
||||
]
|
||||
time = []
|
||||
|
||||
[target."cfg(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), not(target_os = \"wasi\")))".dev-dependencies.wasm-bindgen-test]
|
||||
[target."cfg(all(target_family = \"wasm\", not(target_os = \"wasi\")))".dev-dependencies.wasm-bindgen-test]
|
||||
version = "0.3.0"
|
||||
|
||||
[target."cfg(loom)".dev-dependencies.loom]
|
||||
version = "0.5.2"
|
||||
version = "0.7"
|
||||
features = [
|
||||
"futures",
|
||||
"checkpoint",
|
||||
]
|
||||
|
||||
[target."cfg(not(all(any(target_arch = \"wasm32\", target_arch = \"wasm64\"), target_os = \"unknown\")))".dev-dependencies.rand]
|
||||
[target."cfg(not(all(target_family = \"wasm\", target_os = \"unknown\")))".dev-dependencies.rand]
|
||||
version = "0.8.0"
|
||||
|
||||
[target."cfg(not(any(target_arch = \"wasm32\", target_arch = \"wasm64\")))".dependencies.socket2]
|
||||
version = "0.4.9"
|
||||
[target."cfg(not(target_family = \"wasm\"))".dependencies.socket2]
|
||||
version = "0.5.5"
|
||||
features = ["all"]
|
||||
optional = true
|
||||
|
||||
[target."cfg(not(any(target_arch = \"wasm32\", target_arch = \"wasm64\")))".dev-dependencies.socket2]
|
||||
version = "0.4.9"
|
||||
[target."cfg(not(target_family = \"wasm\"))".dev-dependencies.socket2]
|
||||
version = "0.5.5"
|
||||
|
||||
[target."cfg(not(any(target_arch = \"wasm32\", target_arch = \"wasm64\")))".dev-dependencies.tempfile]
|
||||
[target."cfg(not(target_family = \"wasm\"))".dev-dependencies.tempfile]
|
||||
version = "3.1.0"
|
||||
|
||||
[target."cfg(target_os = \"freebsd\")".dev-dependencies.mio-aio]
|
||||
version = "0.7.0"
|
||||
version = "0.9.0"
|
||||
features = ["tokio"]
|
||||
|
||||
[target."cfg(tokio_taskdump)".dependencies.backtrace]
|
||||
@ -200,7 +200,7 @@ optional = true
|
||||
default-features = false
|
||||
|
||||
[target."cfg(unix)".dependencies.libc]
|
||||
version = "0.2.145"
|
||||
version = "0.2.149"
|
||||
optional = true
|
||||
|
||||
[target."cfg(unix)".dependencies.signal-hook-registry]
|
||||
@ -208,22 +208,23 @@ version = "1.1.1"
|
||||
optional = true
|
||||
|
||||
[target."cfg(unix)".dev-dependencies.libc]
|
||||
version = "0.2.145"
|
||||
version = "0.2.149"
|
||||
|
||||
[target."cfg(unix)".dev-dependencies.nix]
|
||||
version = "0.26"
|
||||
version = "0.29.0"
|
||||
features = [
|
||||
"aio",
|
||||
"fs",
|
||||
"socket",
|
||||
]
|
||||
default-features = false
|
||||
|
||||
[target."cfg(windows)".dependencies.windows-sys]
|
||||
version = "0.48"
|
||||
version = "0.52"
|
||||
optional = true
|
||||
|
||||
[target."cfg(windows)".dev-dependencies.windows-sys]
|
||||
version = "0.48"
|
||||
version = "0.52"
|
||||
features = [
|
||||
"Win32_Foundation",
|
||||
"Win32_Security_Authorization",
|
||||
|
40
third_party/rust/tokio/LICENSE
vendored
40
third_party/rust/tokio/LICENSE
vendored
@ -1,25 +1,21 @@
|
||||
Copyright (c) 2023 Tokio Contributors
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any
|
||||
person obtaining a copy of this software and associated
|
||||
documentation files (the "Software"), to deal in the
|
||||
Software without restriction, including without
|
||||
limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of
|
||||
the Software, and to permit persons to whom the Software
|
||||
is furnished to do so, subject to the following
|
||||
conditions:
|
||||
Copyright (c) Tokio Contributors
|
||||
|
||||
The above copyright notice and this permission notice
|
||||
shall be included in all copies or substantial portions
|
||||
of the Software.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF
|
||||
ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
|
||||
TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
|
||||
PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
|
||||
SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
||||
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
|
||||
IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
DEALINGS IN THE SOFTWARE.
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
37
third_party/rust/tokio/README.md
vendored
37
third_party/rust/tokio/README.md
vendored
@ -56,7 +56,7 @@ Make sure you activated the full features of the tokio crate on Cargo.toml:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
tokio = { version = "1.29.1", features = ["full"] }
|
||||
tokio = { version = "1.39.2", features = ["full"] }
|
||||
```
|
||||
Then, on your main.rs:
|
||||
|
||||
@ -132,6 +132,8 @@ project.
|
||||
In addition to the crates in this repository, the Tokio project also maintains
|
||||
several other libraries, including:
|
||||
|
||||
* [`axum`]: A web application framework that focuses on ergonomics and modularity.
|
||||
|
||||
* [`hyper`]: A fast and correct HTTP/1.1 and HTTP/2 implementation for Rust.
|
||||
|
||||
* [`tonic`]: A gRPC over HTTP/2 implementation focused on high performance, interoperability, and flexibility.
|
||||
@ -142,21 +144,18 @@ several other libraries, including:
|
||||
|
||||
* [`tracing`] (formerly `tokio-trace`): A framework for application-level tracing and async-aware diagnostics.
|
||||
|
||||
* [`rdbc`]: A Rust database connectivity library for MySQL, Postgres and SQLite.
|
||||
|
||||
* [`mio`]: A low-level, cross-platform abstraction over OS I/O APIs that powers
|
||||
`tokio`.
|
||||
* [`mio`]: A low-level, cross-platform abstraction over OS I/O APIs that powers `tokio`.
|
||||
|
||||
* [`bytes`]: Utilities for working with bytes, including efficient byte buffers.
|
||||
|
||||
* [`loom`]: A testing tool for concurrent Rust code
|
||||
* [`loom`]: A testing tool for concurrent Rust code.
|
||||
|
||||
[`axum`]: https://github.com/tokio-rs/axum
|
||||
[`warp`]: https://github.com/seanmonstar/warp
|
||||
[`hyper`]: https://github.com/hyperium/hyper
|
||||
[`tonic`]: https://github.com/hyperium/tonic
|
||||
[`tower`]: https://github.com/tower-rs/tower
|
||||
[`loom`]: https://github.com/tokio-rs/loom
|
||||
[`rdbc`]: https://github.com/tokio-rs/rdbc
|
||||
[`tracing`]: https://github.com/tokio-rs/tracing
|
||||
[`mio`]: https://github.com/tokio-rs/mio
|
||||
[`bytes`]: https://github.com/tokio-rs/bytes
|
||||
@ -187,12 +186,14 @@ When updating this, also update:
|
||||
|
||||
Tokio will keep a rolling MSRV (minimum supported rust version) policy of **at
|
||||
least** 6 months. When increasing the MSRV, the new Rust version must have been
|
||||
released at least six months ago. The current MSRV is 1.56.0.
|
||||
released at least six months ago. The current MSRV is 1.70.
|
||||
|
||||
Note that the MSRV is not increased automatically, and only as part of a minor
|
||||
release. The MSRV history for past minor releases can be found below:
|
||||
|
||||
* 1.27 to now - Rust 1.56
|
||||
* 1.39 to now - Rust 1.70
|
||||
* 1.30 to 1.38 - Rust 1.63
|
||||
* 1.27 to 1.29 - Rust 1.56
|
||||
* 1.17 to 1.26 - Rust 1.49
|
||||
* 1.15 to 1.16 - Rust 1.46
|
||||
* 1.0 to 1.14 - Rust 1.45
|
||||
@ -215,21 +216,29 @@ warrants a patch release with a fix for the bug, it will be backported and
|
||||
released as a new patch release for each LTS minor version. Our current LTS
|
||||
releases are:
|
||||
|
||||
* `1.18.x` - LTS release until June 2023. (MSRV 1.49)
|
||||
* `1.20.x` - LTS release until September 2023. (MSRV 1.49)
|
||||
* `1.25.x` - LTS release until March 2024. (MSRV 1.49)
|
||||
* `1.32.x` - LTS release until September 2024. (MSRV 1.63)
|
||||
* `1.36.x` - LTS release until March 2025. (MSRV 1.63)
|
||||
* `1.38.x` - LTS release until July 2025. (MSRV 1.63)
|
||||
|
||||
Each LTS release will continue to receive backported fixes for at least a year.
|
||||
If you wish to use a fixed minor release in your project, we recommend that you
|
||||
use an LTS release.
|
||||
|
||||
To use a fixed minor version, you can specify the version with a tilde. For
|
||||
example, to specify that you wish to use the newest `1.18.x` patch release, you
|
||||
example, to specify that you wish to use the newest `1.32.x` patch release, you
|
||||
can use the following dependency specification:
|
||||
```text
|
||||
tokio = { version = "~1.18", features = [...] }
|
||||
tokio = { version = "~1.32", features = [...] }
|
||||
```
|
||||
|
||||
### Previous LTS releases
|
||||
|
||||
* `1.8.x` - LTS release until February 2022.
|
||||
* `1.14.x` - LTS release until June 2022.
|
||||
* `1.18.x` - LTS release until June 2023.
|
||||
* `1.20.x` - LTS release until September 2023.
|
||||
* `1.25.x` - LTS release until March 2024.
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the [MIT license].
|
||||
|
192
third_party/rust/tokio/build.rs
vendored
192
third_party/rust/tokio/build.rs
vendored
@ -1,192 +0,0 @@
|
||||
use autocfg::AutoCfg;
|
||||
|
||||
const CONST_THREAD_LOCAL_PROBE: &str = r#"
|
||||
{
|
||||
thread_local! {
|
||||
static MY_PROBE: usize = const { 10 };
|
||||
}
|
||||
|
||||
MY_PROBE.with(|val| *val)
|
||||
}
|
||||
"#;
|
||||
|
||||
const CONST_MUTEX_NEW_PROBE: &str = r#"
|
||||
{
|
||||
static MY_MUTEX: ::std::sync::Mutex<i32> = ::std::sync::Mutex::new(1);
|
||||
*MY_MUTEX.lock().unwrap()
|
||||
}
|
||||
"#;
|
||||
|
||||
const AS_FD_PROBE: &str = r#"
|
||||
{
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(unix)]
|
||||
use std::os::unix::prelude::AsFd as _;
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(windows)]
|
||||
use std::os::windows::prelude::AsSocket as _;
|
||||
#[allow(unused_imports)]
|
||||
#[cfg(target_os = "wasi")]
|
||||
use std::os::wasi::prelude::AsFd as _;
|
||||
}
|
||||
"#;
|
||||
|
||||
const TARGET_HAS_ATOMIC_PROBE: &str = r#"
|
||||
{
|
||||
#[cfg(target_has_atomic = "ptr")]
|
||||
let _ = ();
|
||||
}
|
||||
"#;
|
||||
|
||||
const TARGET_ATOMIC_U64_PROBE: &str = r#"
|
||||
{
|
||||
#[allow(unused_imports)]
|
||||
use std::sync::atomic::AtomicU64 as _;
|
||||
}
|
||||
"#;
|
||||
|
||||
fn main() {
|
||||
let mut enable_const_thread_local = false;
|
||||
let mut enable_target_has_atomic = false;
|
||||
let mut enable_const_mutex_new = false;
|
||||
let mut enable_as_fd = false;
|
||||
let mut target_needs_atomic_u64_fallback = false;
|
||||
|
||||
match AutoCfg::new() {
|
||||
Ok(ac) => {
|
||||
// These checks prefer to call only `probe_rustc_version` if that is
|
||||
// enough to determine whether the feature is supported. This is
|
||||
// because the `probe_expression` call involves a call to rustc,
|
||||
// which the `probe_rustc_version` call avoids.
|
||||
|
||||
// Const-initialized thread locals were stabilized in 1.59.
|
||||
if ac.probe_rustc_version(1, 60) {
|
||||
enable_const_thread_local = true;
|
||||
} else if ac.probe_rustc_version(1, 59) {
|
||||
// This compiler claims to be 1.59, but there are some nightly
|
||||
// compilers that claim to be 1.59 without supporting the
|
||||
// feature. Explicitly probe to check if code using them
|
||||
// compiles.
|
||||
//
|
||||
// The oldest nightly that supports the feature is 2021-12-06.
|
||||
if ac.probe_expression(CONST_THREAD_LOCAL_PROBE) {
|
||||
enable_const_thread_local = true;
|
||||
}
|
||||
}
|
||||
|
||||
// The `target_has_atomic` cfg was stabilized in 1.60.
|
||||
if ac.probe_rustc_version(1, 61) {
|
||||
enable_target_has_atomic = true;
|
||||
} else if ac.probe_rustc_version(1, 60) {
|
||||
// This compiler claims to be 1.60, but there are some nightly
|
||||
// compilers that claim to be 1.60 without supporting the
|
||||
// feature. Explicitly probe to check if code using them
|
||||
// compiles.
|
||||
//
|
||||
// The oldest nightly that supports the feature is 2022-02-11.
|
||||
if ac.probe_expression(TARGET_HAS_ATOMIC_PROBE) {
|
||||
enable_target_has_atomic = true;
|
||||
}
|
||||
}
|
||||
|
||||
// If we can't tell using `target_has_atomic`, tell if the target
|
||||
// has `AtomicU64` by trying to use it.
|
||||
if !enable_target_has_atomic && !ac.probe_expression(TARGET_ATOMIC_U64_PROBE) {
|
||||
target_needs_atomic_u64_fallback = true;
|
||||
}
|
||||
|
||||
// The `Mutex::new` method was made const in 1.63.
|
||||
if ac.probe_rustc_version(1, 64) {
|
||||
enable_const_mutex_new = true;
|
||||
} else if ac.probe_rustc_version(1, 63) {
|
||||
// This compiler claims to be 1.63, but there are some nightly
|
||||
// compilers that claim to be 1.63 without supporting the
|
||||
// feature. Explicitly probe to check if code using them
|
||||
// compiles.
|
||||
//
|
||||
// The oldest nightly that supports the feature is 2022-06-20.
|
||||
if ac.probe_expression(CONST_MUTEX_NEW_PROBE) {
|
||||
enable_const_mutex_new = true;
|
||||
}
|
||||
}
|
||||
|
||||
// The `AsFd` family of traits were made stable in 1.63.
|
||||
if ac.probe_rustc_version(1, 64) {
|
||||
enable_as_fd = true;
|
||||
} else if ac.probe_rustc_version(1, 63) {
|
||||
// This compiler claims to be 1.63, but there are some nightly
|
||||
// compilers that claim to be 1.63 without supporting the
|
||||
// feature. Explicitly probe to check if code using them
|
||||
// compiles.
|
||||
//
|
||||
// The oldest nightly that supports the feature is 2022-06-16.
|
||||
if ac.probe_expression(AS_FD_PROBE) {
|
||||
enable_as_fd = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Err(e) => {
|
||||
// If we couldn't detect the compiler version and features, just
|
||||
// print a warning. This isn't a fatal error: we can still build
|
||||
// Tokio, we just can't enable cfgs automatically.
|
||||
println!(
|
||||
"cargo:warning=tokio: failed to detect compiler features: {}",
|
||||
e
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if !enable_const_thread_local {
|
||||
// To disable this feature on compilers that support it, you can
|
||||
// explicitly pass this flag with the following environment variable:
|
||||
//
|
||||
// RUSTFLAGS="--cfg tokio_no_const_thread_local"
|
||||
autocfg::emit("tokio_no_const_thread_local")
|
||||
}
|
||||
|
||||
if !enable_target_has_atomic {
|
||||
// To disable this feature on compilers that support it, you can
|
||||
// explicitly pass this flag with the following environment variable:
|
||||
//
|
||||
// RUSTFLAGS="--cfg tokio_no_target_has_atomic"
|
||||
autocfg::emit("tokio_no_target_has_atomic")
|
||||
}
|
||||
|
||||
if !enable_const_mutex_new {
|
||||
// To disable this feature on compilers that support it, you can
|
||||
// explicitly pass this flag with the following environment variable:
|
||||
//
|
||||
// RUSTFLAGS="--cfg tokio_no_const_mutex_new"
|
||||
autocfg::emit("tokio_no_const_mutex_new")
|
||||
}
|
||||
|
||||
if !enable_as_fd {
|
||||
// To disable this feature on compilers that support it, you can
|
||||
// explicitly pass this flag with the following environment variable:
|
||||
//
|
||||
// RUSTFLAGS="--cfg tokio_no_as_fd"
|
||||
autocfg::emit("tokio_no_as_fd");
|
||||
}
|
||||
|
||||
if target_needs_atomic_u64_fallback {
|
||||
// To disable this feature on compilers that support it, you can
|
||||
// explicitly pass this flag with the following environment variable:
|
||||
//
|
||||
// RUSTFLAGS="--cfg tokio_no_atomic_u64"
|
||||
autocfg::emit("tokio_no_atomic_u64")
|
||||
}
|
||||
|
||||
let target = ::std::env::var("TARGET").unwrap_or_default();
|
||||
|
||||
// We emit cfgs instead of using `target_family = "wasm"` that requires Rust 1.54.
|
||||
// Note that these cfgs are unavailable in `Cargo.toml`.
|
||||
if target.starts_with("wasm") {
|
||||
autocfg::emit("tokio_wasm");
|
||||
if target.contains("wasi") {
|
||||
autocfg::emit("tokio_wasi");
|
||||
} else {
|
||||
autocfg::emit("tokio_wasm_not_wasi");
|
||||
}
|
||||
}
|
||||
}
|
11
third_party/rust/tokio/external-types.toml
vendored
11
third_party/rust/tokio/external-types.toml
vendored
@ -1,11 +0,0 @@
|
||||
# This config file is for the `cargo-check-external-types` tool that is run in CI.
|
||||
|
||||
# The following are types that are allowed to be exposed in Tokio's public API.
|
||||
# The standard library is allowed by default.
|
||||
allowed_external_types = [
|
||||
"bytes::buf::buf_impl::Buf",
|
||||
"bytes::buf::buf_mut::BufMut",
|
||||
|
||||
"tokio_macros::*",
|
||||
]
|
||||
|
24
third_party/rust/tokio/src/doc/mod.rs
vendored
24
third_party/rust/tokio/src/doc/mod.rs
vendored
@ -20,4 +20,28 @@
|
||||
#[derive(Debug)]
|
||||
pub enum NotDefinedHere {}
|
||||
|
||||
#[cfg(feature = "net")]
|
||||
impl mio::event::Source for NotDefinedHere {
|
||||
fn register(
|
||||
&mut self,
|
||||
registry: &mio::Registry,
|
||||
token: mio::Token,
|
||||
interests: mio::Interest,
|
||||
) -> std::io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn reregister(
|
||||
&mut self,
|
||||
registry: &mio::Registry,
|
||||
token: mio::Token,
|
||||
interests: mio::Interest,
|
||||
) -> std::io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
fn deregister(&mut self, registry: &mio::Registry) -> std::io::Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(any(feature = "net", feature = "fs"))]
|
||||
pub mod os;
|
||||
|
45
third_party/rust/tokio/src/doc/os.rs
vendored
45
third_party/rust/tokio/src/doc/os.rs
vendored
@ -1,64 +1,67 @@
|
||||
//! See [std::os](https://doc.rust-lang.org/std/os/index.html).
|
||||
//! See [`std::os`](https://doc.rust-lang.org/std/os/index.html).
|
||||
|
||||
/// Platform-specific extensions to `std` for Windows.
|
||||
///
|
||||
/// See [std::os::windows](https://doc.rust-lang.org/std/os/windows/index.html).
|
||||
/// See [`std::os::windows`](https://doc.rust-lang.org/std/os/windows/index.html).
|
||||
pub mod windows {
|
||||
/// Windows-specific extensions to general I/O primitives.
|
||||
///
|
||||
/// See [std::os::windows::io](https://doc.rust-lang.org/std/os/windows/io/index.html).
|
||||
/// See [`std::os::windows::io`](https://doc.rust-lang.org/std/os/windows/io/index.html).
|
||||
pub mod io {
|
||||
/// See [std::os::windows::io::RawHandle](https://doc.rust-lang.org/std/os/windows/io/type.RawHandle.html)
|
||||
/// See [`std::os::windows::io::RawHandle`](https://doc.rust-lang.org/std/os/windows/io/type.RawHandle.html)
|
||||
pub type RawHandle = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [std::os::windows::io::AsRawHandle](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawHandle.html)
|
||||
/// See [`std::os::windows::io::OwnedHandle`](https://doc.rust-lang.org/std/os/windows/io/struct.OwnedHandle.html)
|
||||
pub type OwnedHandle = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [`std::os::windows::io::AsRawHandle`](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawHandle.html)
|
||||
pub trait AsRawHandle {
|
||||
/// See [std::os::windows::io::AsRawHandle::as_raw_handle](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawHandle.html#tymethod.as_raw_handle)
|
||||
/// See [`std::os::windows::io::AsRawHandle::as_raw_handle`](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawHandle.html#tymethod.as_raw_handle)
|
||||
fn as_raw_handle(&self) -> RawHandle;
|
||||
}
|
||||
|
||||
/// See [std::os::windows::io::FromRawHandle](https://doc.rust-lang.org/std/os/windows/io/trait.FromRawHandle.html)
|
||||
/// See [`std::os::windows::io::FromRawHandle`](https://doc.rust-lang.org/std/os/windows/io/trait.FromRawHandle.html)
|
||||
pub trait FromRawHandle {
|
||||
/// See [std::os::windows::io::FromRawHandle::from_raw_handle](https://doc.rust-lang.org/std/os/windows/io/trait.FromRawHandle.html#tymethod.from_raw_handle)
|
||||
/// See [`std::os::windows::io::FromRawHandle::from_raw_handle`](https://doc.rust-lang.org/std/os/windows/io/trait.FromRawHandle.html#tymethod.from_raw_handle)
|
||||
unsafe fn from_raw_handle(handle: RawHandle) -> Self;
|
||||
}
|
||||
|
||||
/// See [std::os::windows::io::RawSocket](https://doc.rust-lang.org/std/os/windows/io/type.RawSocket.html)
|
||||
/// See [`std::os::windows::io::RawSocket`](https://doc.rust-lang.org/std/os/windows/io/type.RawSocket.html)
|
||||
pub type RawSocket = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [std::os::windows::io::AsRawSocket](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawSocket.html)
|
||||
/// See [`std::os::windows::io::AsRawSocket`](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawSocket.html)
|
||||
pub trait AsRawSocket {
|
||||
/// See [std::os::windows::io::AsRawSocket::as_raw_socket](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawSocket.html#tymethod.as_raw_socket)
|
||||
/// See [`std::os::windows::io::AsRawSocket::as_raw_socket`](https://doc.rust-lang.org/std/os/windows/io/trait.AsRawSocket.html#tymethod.as_raw_socket)
|
||||
fn as_raw_socket(&self) -> RawSocket;
|
||||
}
|
||||
|
||||
/// See [std::os::windows::io::FromRawSocket](https://doc.rust-lang.org/std/os/windows/io/trait.FromRawSocket.html)
|
||||
/// See [`std::os::windows::io::FromRawSocket`](https://doc.rust-lang.org/std/os/windows/io/trait.FromRawSocket.html)
|
||||
pub trait FromRawSocket {
|
||||
/// See [std::os::windows::io::FromRawSocket::from_raw_socket](https://doc.rust-lang.org/std/os/windows/io/trait.FromRawSocket.html#tymethod.from_raw_socket)
|
||||
/// See [`std::os::windows::io::FromRawSocket::from_raw_socket`](https://doc.rust-lang.org/std/os/windows/io/trait.FromRawSocket.html#tymethod.from_raw_socket)
|
||||
unsafe fn from_raw_socket(sock: RawSocket) -> Self;
|
||||
}
|
||||
|
||||
/// See [std::os::windows::io::IntoRawSocket](https://doc.rust-lang.org/std/os/windows/io/trait.IntoRawSocket.html)
|
||||
/// See [`std::os::windows::io::IntoRawSocket`](https://doc.rust-lang.org/std/os/windows/io/trait.IntoRawSocket.html)
|
||||
pub trait IntoRawSocket {
|
||||
/// See [std::os::windows::io::IntoRawSocket::into_raw_socket](https://doc.rust-lang.org/std/os/windows/io/trait.IntoRawSocket.html#tymethod.into_raw_socket)
|
||||
/// See [`std::os::windows::io::IntoRawSocket::into_raw_socket`](https://doc.rust-lang.org/std/os/windows/io/trait.IntoRawSocket.html#tymethod.into_raw_socket)
|
||||
fn into_raw_socket(self) -> RawSocket;
|
||||
}
|
||||
|
||||
/// See [std::os::windows::io::BorrowedHandle](https://doc.rust-lang.org/std/os/windows/io/struct.BorrowedHandle.html)
|
||||
/// See [`std::os::windows::io::BorrowedHandle`](https://doc.rust-lang.org/std/os/windows/io/struct.BorrowedHandle.html)
|
||||
pub type BorrowedHandle<'handle> = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [std::os::windows::io::AsHandle](https://doc.rust-lang.org/std/os/windows/io/trait.AsHandle.html)
|
||||
/// See [`std::os::windows::io::AsHandle`](https://doc.rust-lang.org/std/os/windows/io/trait.AsHandle.html)
|
||||
pub trait AsHandle {
|
||||
/// See [std::os::windows::io::AsHandle::as_handle](https://doc.rust-lang.org/std/os/windows/io/trait.AsHandle.html#tymethod.as_handle)
|
||||
/// See [`std::os::windows::io::AsHandle::as_handle`](https://doc.rust-lang.org/std/os/windows/io/trait.AsHandle.html#tymethod.as_handle)
|
||||
fn as_handle(&self) -> BorrowedHandle<'_>;
|
||||
}
|
||||
|
||||
/// See [std::os::windows::io::BorrowedSocket](https://doc.rust-lang.org/std/os/windows/io/struct.BorrowedSocket.html)
|
||||
/// See [`std::os::windows::io::BorrowedSocket`](https://doc.rust-lang.org/std/os/windows/io/struct.BorrowedSocket.html)
|
||||
pub type BorrowedSocket<'socket> = crate::doc::NotDefinedHere;
|
||||
|
||||
/// See [std::os::windows::io::AsSocket](https://doc.rust-lang.org/std/os/windows/io/trait.AsSocket.html)
|
||||
/// See [`std::os::windows::io::AsSocket`](https://doc.rust-lang.org/std/os/windows/io/trait.AsSocket.html)
|
||||
pub trait AsSocket {
|
||||
/// See [std::os::windows::io::AsSocket::as_socket](https://doc.rust-lang.org/std/os/windows/io/trait.AsSocket.html#tymethod.as_socket)
|
||||
/// See [`std::os::windows::io::AsSocket::as_socket`](https://doc.rust-lang.org/std/os/windows/io/trait.AsSocket.html#tymethod.as_socket)
|
||||
fn as_socket(&self) -> BorrowedSocket<'_>;
|
||||
}
|
||||
}
|
||||
|
@ -6,9 +6,7 @@ use std::path::{Path, PathBuf};
|
||||
/// Returns the canonical, absolute form of a path with all intermediate
|
||||
/// components normalized and symbolic links resolved.
|
||||
///
|
||||
/// This is an async version of [`std::fs::canonicalize`][std]
|
||||
///
|
||||
/// [std]: std::fs::canonicalize
|
||||
/// This is an async version of [`std::fs::canonicalize`].
|
||||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
|
4
third_party/rust/tokio/src/fs/copy.rs
vendored
4
third_party/rust/tokio/src/fs/copy.rs
vendored
@ -5,9 +5,7 @@ use std::path::Path;
|
||||
/// of the original file to the destination file.
|
||||
/// This function will overwrite the contents of to.
|
||||
///
|
||||
/// This is the async equivalent of [`std::fs::copy`][std].
|
||||
///
|
||||
/// [std]: fn@std::fs::copy
|
||||
/// This is the async equivalent of [`std::fs::copy`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
|
4
third_party/rust/tokio/src/fs/create_dir.rs
vendored
4
third_party/rust/tokio/src/fs/create_dir.rs
vendored
@ -5,9 +5,7 @@ use std::path::Path;
|
||||
|
||||
/// Creates a new, empty directory at the provided path.
|
||||
///
|
||||
/// This is an async version of [`std::fs::create_dir`][std]
|
||||
///
|
||||
/// [std]: std::fs::create_dir
|
||||
/// This is an async version of [`std::fs::create_dir`].
|
||||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
|
@ -6,9 +6,7 @@ use std::path::Path;
|
||||
/// Recursively creates a directory and all of its parent components if they
|
||||
/// are missing.
|
||||
///
|
||||
/// This is an async version of [`std::fs::create_dir_all`][std]
|
||||
///
|
||||
/// [std]: std::fs::create_dir_all
|
||||
/// This is an async version of [`std::fs::create_dir_all`].
|
||||
///
|
||||
/// # Platform-specific behavior
|
||||
///
|
||||
|
16
third_party/rust/tokio/src/fs/dir_builder.rs
vendored
16
third_party/rust/tokio/src/fs/dir_builder.rs
vendored
@ -7,8 +7,6 @@ use std::path::Path;
|
||||
///
|
||||
/// This is a specialized version of [`std::fs::DirBuilder`] for usage on
|
||||
/// the Tokio runtime.
|
||||
///
|
||||
/// [std::fs::DirBuilder]: std::fs::DirBuilder
|
||||
#[derive(Debug, Default)]
|
||||
pub struct DirBuilder {
|
||||
/// Indicates whether to create parent directories if they are missing.
|
||||
@ -23,9 +21,7 @@ impl DirBuilder {
|
||||
/// Creates a new set of options with default mode/security settings for all
|
||||
/// platforms and also non-recursive.
|
||||
///
|
||||
/// This is an async version of [`std::fs::DirBuilder::new`][std]
|
||||
///
|
||||
/// [std]: std::fs::DirBuilder::new
|
||||
/// This is an async version of [`std::fs::DirBuilder::new`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -35,7 +31,7 @@ impl DirBuilder {
|
||||
/// let builder = DirBuilder::new();
|
||||
/// ```
|
||||
pub fn new() -> Self {
|
||||
Default::default()
|
||||
DirBuilder::default()
|
||||
}
|
||||
|
||||
/// Indicates whether to create directories recursively (including all parent directories).
|
||||
@ -43,9 +39,7 @@ impl DirBuilder {
|
||||
///
|
||||
/// This option defaults to `false`.
|
||||
///
|
||||
/// This is an async version of [`std::fs::DirBuilder::recursive`][std]
|
||||
///
|
||||
/// [std]: std::fs::DirBuilder::recursive
|
||||
/// This is an async version of [`std::fs::DirBuilder::recursive`].
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -65,9 +59,7 @@ impl DirBuilder {
|
||||
/// It is considered an error if the directory already exists unless
|
||||
/// recursive mode is enabled.
|
||||
///
|
||||
/// This is an async version of [`std::fs::DirBuilder::create`][std]
|
||||
///
|
||||
/// [std]: std::fs::DirBuilder::create
|
||||
/// This is an async version of [`std::fs::DirBuilder::create`].
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
|
291
third_party/rust/tokio/src/fs/file.rs
vendored
291
third_party/rust/tokio/src/fs/file.rs
vendored
@ -2,9 +2,8 @@
|
||||
//!
|
||||
//! [`File`]: File
|
||||
|
||||
use self::State::*;
|
||||
use crate::fs::asyncify;
|
||||
use crate::io::blocking::Buf;
|
||||
use crate::fs::{asyncify, OpenOptions};
|
||||
use crate::io::blocking::{Buf, DEFAULT_MAX_BUF_SIZE};
|
||||
use crate::io::{AsyncRead, AsyncSeek, AsyncWrite, ReadBuf};
|
||||
use crate::sync::Mutex;
|
||||
|
||||
@ -17,7 +16,6 @@ use std::pin::Pin;
|
||||
use std::sync::Arc;
|
||||
use std::task::Context;
|
||||
use std::task::Poll;
|
||||
use std::task::Poll::*;
|
||||
|
||||
#[cfg(test)]
|
||||
use super::mocks::JoinHandle;
|
||||
@ -34,7 +32,7 @@ use std::fs::File as StdFile;
|
||||
|
||||
/// A reference to an open file on the filesystem.
|
||||
///
|
||||
/// This is a specialized version of [`std::fs::File`][std] for usage from the
|
||||
/// This is a specialized version of [`std::fs::File`] for usage from the
|
||||
/// Tokio runtime.
|
||||
///
|
||||
/// An instance of a `File` can be read and/or written depending on what options
|
||||
@ -52,7 +50,6 @@ use std::fs::File as StdFile;
|
||||
/// Reading and writing to a `File` is usually done using the convenience
|
||||
/// methods found on the [`AsyncReadExt`] and [`AsyncWriteExt`] traits.
|
||||
///
|
||||
/// [std]: struct@std::fs::File
|
||||
/// [`AsyncSeek`]: trait@crate::io::AsyncSeek
|
||||
/// [`flush`]: fn@crate::io::AsyncWriteExt::flush
|
||||
/// [`sync_all`]: fn@crate::fs::File::sync_all
|
||||
@ -93,6 +90,7 @@ use std::fs::File as StdFile;
|
||||
pub struct File {
|
||||
std: Arc<StdFile>,
|
||||
inner: Mutex<Inner>,
|
||||
max_buf_size: usize,
|
||||
}
|
||||
|
||||
struct Inner {
|
||||
@ -124,13 +122,11 @@ impl File {
|
||||
///
|
||||
/// See [`OpenOptions`] for more details.
|
||||
///
|
||||
/// [`OpenOptions`]: super::OpenOptions
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// This function will return an error if called from outside of the Tokio
|
||||
/// runtime or if path does not already exist. Other errors may also be
|
||||
/// returned according to OpenOptions::open.
|
||||
/// returned according to `OpenOptions::open`.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -167,8 +163,6 @@ impl File {
|
||||
///
|
||||
/// See [`OpenOptions`] for more details.
|
||||
///
|
||||
/// [`OpenOptions`]: super::OpenOptions
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
/// Results in an error if called from outside of the Tokio runtime or if
|
||||
@ -199,10 +193,78 @@ impl File {
|
||||
Ok(File::from_std(std_file))
|
||||
}
|
||||
|
||||
/// Converts a [`std::fs::File`][std] to a [`tokio::fs::File`][file].
|
||||
/// Opens a file in read-write mode.
|
||||
///
|
||||
/// [std]: std::fs::File
|
||||
/// [file]: File
|
||||
/// This function will create a file if it does not exist, or return an error
|
||||
/// if it does. This way, if the call succeeds, the file returned is guaranteed
|
||||
/// to be new.
|
||||
///
|
||||
/// This option is useful because it is atomic. Otherwise between checking
|
||||
/// whether a file exists and creating a new one, the file may have been
|
||||
/// created by another process (a TOCTOU race condition / attack).
|
||||
///
|
||||
/// This can also be written using `File::options().read(true).write(true).create_new(true).open(...)`.
|
||||
///
|
||||
/// See [`OpenOptions`] for more details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::fs::File;
|
||||
/// use tokio::io::AsyncWriteExt;
|
||||
///
|
||||
/// # async fn dox() -> std::io::Result<()> {
|
||||
/// let mut file = File::create_new("foo.txt").await?;
|
||||
/// file.write_all(b"hello, world!").await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
///
|
||||
/// The [`write_all`] method is defined on the [`AsyncWriteExt`] trait.
|
||||
///
|
||||
/// [`write_all`]: fn@crate::io::AsyncWriteExt::write_all
|
||||
/// [`AsyncWriteExt`]: trait@crate::io::AsyncWriteExt
|
||||
pub async fn create_new<P: AsRef<Path>>(path: P) -> std::io::Result<File> {
|
||||
Self::options()
|
||||
.read(true)
|
||||
.write(true)
|
||||
.create_new(true)
|
||||
.open(path)
|
||||
.await
|
||||
}
|
||||
|
||||
/// Returns a new [`OpenOptions`] object.
|
||||
///
|
||||
/// This function returns a new `OpenOptions` object that you can use to
|
||||
/// open or create a file with specific options if `open()` or `create()`
|
||||
/// are not appropriate.
|
||||
///
|
||||
/// It is equivalent to `OpenOptions::new()`, but allows you to write more
|
||||
/// readable code. Instead of
|
||||
/// `OpenOptions::new().append(true).open("example.log")`,
|
||||
/// you can write `File::options().append(true).open("example.log")`. This
|
||||
/// also avoids the need to import `OpenOptions`.
|
||||
///
|
||||
/// See the [`OpenOptions::new`] function for more details.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::fs::File;
|
||||
/// use tokio::io::AsyncWriteExt;
|
||||
///
|
||||
/// # async fn dox() -> std::io::Result<()> {
|
||||
/// let mut f = File::options().append(true).open("example.log").await?;
|
||||
/// f.write_all(b"new line\n").await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
#[must_use]
|
||||
pub fn options() -> OpenOptions {
|
||||
OpenOptions::new()
|
||||
}
|
||||
|
||||
/// Converts a [`std::fs::File`] to a [`tokio::fs::File`](File).
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -220,6 +282,7 @@ impl File {
|
||||
last_write_err: None,
|
||||
pos: 0,
|
||||
}),
|
||||
max_buf_size: DEFAULT_MAX_BUF_SIZE,
|
||||
}
|
||||
}
|
||||
|
||||
@ -324,7 +387,7 @@ impl File {
|
||||
inner.complete_inflight().await;
|
||||
|
||||
let mut buf = match inner.state {
|
||||
Idle(ref mut buf_cell) => buf_cell.take().unwrap(),
|
||||
State::Idle(ref mut buf_cell) => buf_cell.take().unwrap(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
@ -336,24 +399,24 @@ impl File {
|
||||
|
||||
let std = self.std.clone();
|
||||
|
||||
inner.state = Busy(spawn_blocking(move || {
|
||||
inner.state = State::Busy(spawn_blocking(move || {
|
||||
let res = if let Some(seek) = seek {
|
||||
(&*std).seek(seek).and_then(|_| std.set_len(size))
|
||||
} else {
|
||||
std.set_len(size)
|
||||
}
|
||||
.map(|_| 0); // the value is discarded later
|
||||
.map(|()| 0); // the value is discarded later
|
||||
|
||||
// Return the result as a seek
|
||||
(Operation::Seek(res), buf)
|
||||
}));
|
||||
|
||||
let (op, buf) = match inner.state {
|
||||
Idle(_) => unreachable!(),
|
||||
Busy(ref mut rx) => rx.await?,
|
||||
State::Idle(_) => unreachable!(),
|
||||
State::Busy(ref mut rx) => rx.await?,
|
||||
};
|
||||
|
||||
inner.state = Idle(Some(buf));
|
||||
inner.state = State::Idle(Some(buf));
|
||||
|
||||
match op {
|
||||
Operation::Seek(res) => res.map(|pos| {
|
||||
@ -405,13 +468,11 @@ impl File {
|
||||
Ok(File::from_std(std_file))
|
||||
}
|
||||
|
||||
/// Destructures `File` into a [`std::fs::File`][std]. This function is
|
||||
/// Destructures `File` into a [`std::fs::File`]. This function is
|
||||
/// async to allow any in-flight operations to complete.
|
||||
///
|
||||
/// Use `File::try_into_std` to attempt conversion immediately.
|
||||
///
|
||||
/// [std]: std::fs::File
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
@ -428,9 +489,7 @@ impl File {
|
||||
Arc::try_unwrap(self.std).expect("Arc::try_unwrap failed")
|
||||
}
|
||||
|
||||
/// Tries to immediately destructure `File` into a [`std::fs::File`][std].
|
||||
///
|
||||
/// [std]: std::fs::File
|
||||
/// Tries to immediately destructure `File` into a [`std::fs::File`].
|
||||
///
|
||||
/// # Errors
|
||||
///
|
||||
@ -491,6 +550,34 @@ impl File {
|
||||
let std = self.std.clone();
|
||||
asyncify(move || std.set_permissions(perm)).await
|
||||
}
|
||||
|
||||
/// Set the maximum buffer size for the underlying [`AsyncRead`] / [`AsyncWrite`] operation.
|
||||
///
|
||||
/// Although Tokio uses a sensible default value for this buffer size, this function would be
|
||||
/// useful for changing that default depending on the situation.
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use tokio::fs::File;
|
||||
/// use tokio::io::AsyncWriteExt;
|
||||
///
|
||||
/// # async fn dox() -> std::io::Result<()> {
|
||||
/// let mut file = File::open("foo.txt").await?;
|
||||
///
|
||||
/// // Set maximum buffer size to 8 MiB
|
||||
/// file.set_max_buf_size(8 * 1024 * 1024);
|
||||
///
|
||||
/// let mut buf = vec![1; 1024 * 1024 * 1024];
|
||||
///
|
||||
/// // Write the 1 GiB buffer in chunks up to 8 MiB each.
|
||||
/// file.write_all(&mut buf).await?;
|
||||
/// # Ok(())
|
||||
/// # }
|
||||
/// ```
|
||||
pub fn set_max_buf_size(&mut self, max_buf_size: usize) {
|
||||
self.max_buf_size = max_buf_size;
|
||||
}
|
||||
}
|
||||
|
||||
impl AsyncRead for File {
|
||||
@ -505,51 +592,51 @@ impl AsyncRead for File {
|
||||
|
||||
loop {
|
||||
match inner.state {
|
||||
Idle(ref mut buf_cell) => {
|
||||
State::Idle(ref mut buf_cell) => {
|
||||
let mut buf = buf_cell.take().unwrap();
|
||||
|
||||
if !buf.is_empty() {
|
||||
buf.copy_to(dst);
|
||||
*buf_cell = Some(buf);
|
||||
return Ready(Ok(()));
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
|
||||
buf.ensure_capacity_for(dst);
|
||||
buf.ensure_capacity_for(dst, me.max_buf_size);
|
||||
let std = me.std.clone();
|
||||
|
||||
inner.state = Busy(spawn_blocking(move || {
|
||||
inner.state = State::Busy(spawn_blocking(move || {
|
||||
let res = buf.read_from(&mut &*std);
|
||||
(Operation::Read(res), buf)
|
||||
}));
|
||||
}
|
||||
Busy(ref mut rx) => {
|
||||
State::Busy(ref mut rx) => {
|
||||
let (op, mut buf) = ready!(Pin::new(rx).poll(cx))?;
|
||||
|
||||
match op {
|
||||
Operation::Read(Ok(_)) => {
|
||||
buf.copy_to(dst);
|
||||
inner.state = Idle(Some(buf));
|
||||
return Ready(Ok(()));
|
||||
inner.state = State::Idle(Some(buf));
|
||||
return Poll::Ready(Ok(()));
|
||||
}
|
||||
Operation::Read(Err(e)) => {
|
||||
assert!(buf.is_empty());
|
||||
|
||||
inner.state = Idle(Some(buf));
|
||||
return Ready(Err(e));
|
||||
inner.state = State::Idle(Some(buf));
|
||||
return Poll::Ready(Err(e));
|
||||
}
|
||||
Operation::Write(Ok(_)) => {
|
||||
Operation::Write(Ok(())) => {
|
||||
assert!(buf.is_empty());
|
||||
inner.state = Idle(Some(buf));
|
||||
inner.state = State::Idle(Some(buf));
|
||||
continue;
|
||||
}
|
||||
Operation::Write(Err(e)) => {
|
||||
assert!(inner.last_write_err.is_none());
|
||||
inner.last_write_err = Some(e.kind());
|
||||
inner.state = Idle(Some(buf));
|
||||
inner.state = State::Idle(Some(buf));
|
||||
}
|
||||
Operation::Seek(result) => {
|
||||
assert!(buf.is_empty());
|
||||
inner.state = Idle(Some(buf));
|
||||
inner.state = State::Idle(Some(buf));
|
||||
if let Ok(pos) = result {
|
||||
inner.pos = pos;
|
||||
}
|
||||
@ -568,11 +655,11 @@ impl AsyncSeek for File {
|
||||
let inner = me.inner.get_mut();
|
||||
|
||||
match inner.state {
|
||||
Busy(_) => Err(io::Error::new(
|
||||
State::Busy(_) => Err(io::Error::new(
|
||||
io::ErrorKind::Other,
|
||||
"other file operation is pending, call poll_complete before start_seek",
|
||||
)),
|
||||
Idle(ref mut buf_cell) => {
|
||||
State::Idle(ref mut buf_cell) => {
|
||||
let mut buf = buf_cell.take().unwrap();
|
||||
|
||||
// Factor in any unread data from the buf
|
||||
@ -586,7 +673,7 @@ impl AsyncSeek for File {
|
||||
|
||||
let std = me.std.clone();
|
||||
|
||||
inner.state = Busy(spawn_blocking(move || {
|
||||
inner.state = State::Busy(spawn_blocking(move || {
|
||||
let res = (&*std).seek(pos);
|
||||
(Operation::Seek(res), buf)
|
||||
}));
|
||||
@ -601,10 +688,10 @@ impl AsyncSeek for File {
|
||||
|
||||
loop {
|
||||
match inner.state {
|
||||
Idle(_) => return Poll::Ready(Ok(inner.pos)),
|
||||
Busy(ref mut rx) => {
|
||||
State::Idle(_) => return Poll::Ready(Ok(inner.pos)),
|
||||
State::Busy(ref mut rx) => {
|
||||
let (op, buf) = ready!(Pin::new(rx).poll(cx))?;
|
||||
inner.state = Idle(Some(buf));
|
||||
inner.state = State::Idle(Some(buf));
|
||||
|
||||
match op {
|
||||
Operation::Read(_) => {}
|
||||
@ -617,7 +704,7 @@ impl AsyncSeek for File {
|
||||
if let Ok(pos) = res {
|
||||
inner.pos = pos;
|
||||
}
|
||||
return Ready(res);
|
||||
return Poll::Ready(res);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -637,12 +724,12 @@ impl AsyncWrite for File {
|
||||
let inner = me.inner.get_mut();
|
||||
|
||||
if let Some(e) = inner.last_write_err.take() {
|
||||
return Ready(Err(e.into()));
|
||||
return Poll::Ready(Err(e.into()));
|
||||
}
|
||||
|
||||
loop {
|
||||
match inner.state {
|
||||
Idle(ref mut buf_cell) => {
|
||||
State::Idle(ref mut buf_cell) => {
|
||||
let mut buf = buf_cell.take().unwrap();
|
||||
|
||||
let seek = if !buf.is_empty() {
|
||||
@ -651,7 +738,7 @@ impl AsyncWrite for File {
|
||||
None
|
||||
};
|
||||
|
||||
let n = buf.copy_from(src);
|
||||
let n = buf.copy_from(src, me.max_buf_size);
|
||||
let std = me.std.clone();
|
||||
|
||||
let blocking_task_join_handle = spawn_mandatory_blocking(move || {
|
||||
@ -667,13 +754,13 @@ impl AsyncWrite for File {
|
||||
io::Error::new(io::ErrorKind::Other, "background task failed")
|
||||
})?;
|
||||
|
||||
inner.state = Busy(blocking_task_join_handle);
|
||||
inner.state = State::Busy(blocking_task_join_handle);
|
||||
|
||||
return Ready(Ok(n));
|
||||
return Poll::Ready(Ok(n));
|
||||
}
|
||||
Busy(ref mut rx) => {
|
||||
State::Busy(ref mut rx) => {
|
||||
let (op, buf) = ready!(Pin::new(rx).poll(cx))?;
|
||||
inner.state = Idle(Some(buf));
|
||||
inner.state = State::Idle(Some(buf));
|
||||
|
||||
match op {
|
||||
Operation::Read(_) => {
|
||||
@ -698,6 +785,81 @@ impl AsyncWrite for File {
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_write_vectored(
|
||||
self: Pin<&mut Self>,
|
||||
cx: &mut Context<'_>,
|
||||
bufs: &[io::IoSlice<'_>],
|
||||
) -> Poll<Result<usize, io::Error>> {
|
||||
ready!(crate::trace::trace_leaf(cx));
|
||||
let me = self.get_mut();
|
||||
let inner = me.inner.get_mut();
|
||||
|
||||
if let Some(e) = inner.last_write_err.take() {
|
||||
return Poll::Ready(Err(e.into()));
|
||||
}
|
||||
|
||||
loop {
|
||||
match inner.state {
|
||||
State::Idle(ref mut buf_cell) => {
|
||||
let mut buf = buf_cell.take().unwrap();
|
||||
|
||||
let seek = if !buf.is_empty() {
|
||||
Some(SeekFrom::Current(buf.discard_read()))
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
let n = buf.copy_from_bufs(bufs, me.max_buf_size);
|
||||
let std = me.std.clone();
|
||||
|
||||
let blocking_task_join_handle = spawn_mandatory_blocking(move || {
|
||||
let res = if let Some(seek) = seek {
|
||||
(&*std).seek(seek).and_then(|_| buf.write_to(&mut &*std))
|
||||
} else {
|
||||
buf.write_to(&mut &*std)
|
||||
};
|
||||
|
||||
(Operation::Write(res), buf)
|
||||
})
|
||||
.ok_or_else(|| {
|
||||
io::Error::new(io::ErrorKind::Other, "background task failed")
|
||||
})?;
|
||||
|
||||
inner.state = State::Busy(blocking_task_join_handle);
|
||||
|
||||
return Poll::Ready(Ok(n));
|
||||
}
|
||||
State::Busy(ref mut rx) => {
|
||||
let (op, buf) = ready!(Pin::new(rx).poll(cx))?;
|
||||
inner.state = State::Idle(Some(buf));
|
||||
|
||||
match op {
|
||||
Operation::Read(_) => {
|
||||
// We don't care about the result here. The fact
|
||||
// that the cursor has advanced will be reflected in
|
||||
// the next iteration of the loop
|
||||
continue;
|
||||
}
|
||||
Operation::Write(res) => {
|
||||
// If the previous write was successful, continue.
|
||||
// Otherwise, error.
|
||||
res?;
|
||||
continue;
|
||||
}
|
||||
Operation::Seek(_) => {
|
||||
// Ignore the seek
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn is_write_vectored(&self) -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
fn poll_flush(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
||||
ready!(crate::trace::trace_leaf(cx));
|
||||
let inner = self.inner.get_mut();
|
||||
@ -731,7 +893,7 @@ impl std::os::unix::io::AsRawFd for File {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(all(unix, not(tokio_no_as_fd)))]
|
||||
#[cfg(unix)]
|
||||
impl std::os::unix::io::AsFd for File {
|
||||
fn as_fd(&self) -> std::os::unix::io::BorrowedFd<'_> {
|
||||
unsafe {
|
||||
@ -748,9 +910,7 @@ impl std::os::unix::io::FromRawFd for File {
|
||||
}
|
||||
|
||||
cfg_windows! {
|
||||
use crate::os::windows::io::{AsRawHandle, FromRawHandle, RawHandle};
|
||||
#[cfg(not(tokio_no_as_fd))]
|
||||
use crate::os::windows::io::{AsHandle, BorrowedHandle};
|
||||
use crate::os::windows::io::{AsRawHandle, FromRawHandle, RawHandle, AsHandle, BorrowedHandle};
|
||||
|
||||
impl AsRawHandle for File {
|
||||
fn as_raw_handle(&self) -> RawHandle {
|
||||
@ -758,7 +918,6 @@ cfg_windows! {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(tokio_no_as_fd))]
|
||||
impl AsHandle for File {
|
||||
fn as_handle(&self) -> BorrowedHandle<'_> {
|
||||
unsafe {
|
||||
@ -780,7 +939,7 @@ impl Inner {
|
||||
async fn complete_inflight(&mut self) {
|
||||
use crate::future::poll_fn;
|
||||
|
||||
poll_fn(|cx| self.poll_complete_inflight(cx)).await
|
||||
poll_fn(|cx| self.poll_complete_inflight(cx)).await;
|
||||
}
|
||||
|
||||
fn poll_complete_inflight(&mut self, cx: &mut Context<'_>) -> Poll<()> {
|
||||
@ -797,21 +956,21 @@ impl Inner {
|
||||
|
||||
fn poll_flush(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
|
||||
if let Some(e) = self.last_write_err.take() {
|
||||
return Ready(Err(e.into()));
|
||||
return Poll::Ready(Err(e.into()));
|
||||
}
|
||||
|
||||
let (op, buf) = match self.state {
|
||||
Idle(_) => return Ready(Ok(())),
|
||||
Busy(ref mut rx) => ready!(Pin::new(rx).poll(cx))?,
|
||||
State::Idle(_) => return Poll::Ready(Ok(())),
|
||||
State::Busy(ref mut rx) => ready!(Pin::new(rx).poll(cx))?,
|
||||
};
|
||||
|
||||
// The buffer is not used here
|
||||
self.state = Idle(Some(buf));
|
||||
self.state = State::Idle(Some(buf));
|
||||
|
||||
match op {
|
||||
Operation::Read(_) => Ready(Ok(())),
|
||||
Operation::Write(res) => Ready(res),
|
||||
Operation::Seek(_) => Ready(Ok(())),
|
||||
Operation::Read(_) => Poll::Ready(Ok(())),
|
||||
Operation::Write(res) => Poll::Ready(res),
|
||||
Operation::Seek(_) => Poll::Ready(Ok(())),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
4
third_party/rust/tokio/src/fs/file/tests.rs
vendored
4
third_party/rust/tokio/src/fs/file/tests.rs
vendored
@ -231,7 +231,7 @@ fn flush_while_idle() {
|
||||
#[cfg_attr(miri, ignore)] // takes a really long time with miri
|
||||
fn read_with_buffer_larger_than_max() {
|
||||
// Chunks
|
||||
let chunk_a = crate::io::blocking::MAX_BUF;
|
||||
let chunk_a = crate::io::blocking::DEFAULT_MAX_BUF_SIZE;
|
||||
let chunk_b = chunk_a * 2;
|
||||
let chunk_c = chunk_a * 3;
|
||||
let chunk_d = chunk_a * 4;
|
||||
@ -303,7 +303,7 @@ fn read_with_buffer_larger_than_max() {
|
||||
#[cfg_attr(miri, ignore)] // takes a really long time with miri
|
||||
fn write_with_buffer_larger_than_max() {
|
||||
// Chunks
|
||||
let chunk_a = crate::io::blocking::MAX_BUF;
|
||||
let chunk_a = crate::io::blocking::DEFAULT_MAX_BUF_SIZE;
|
||||
let chunk_b = chunk_a * 2;
|
||||
let chunk_c = chunk_a * 3;
|
||||
let chunk_d = chunk_a * 4;
|
||||
|
4
third_party/rust/tokio/src/fs/hard_link.rs
vendored
4
third_party/rust/tokio/src/fs/hard_link.rs
vendored
@ -5,9 +5,7 @@ use std::path::Path;
|
||||
|
||||
/// Creates a new hard link on the filesystem.
|
||||
///
|
||||
/// This is an async version of [`std::fs::hard_link`][std]
|
||||
///
|
||||
/// [std]: std::fs::hard_link
|
||||
/// This is an async version of [`std::fs::hard_link`].
|
||||
///
|
||||
/// The `dst` path will be a link pointing to the `src` path. Note that systems
|
||||
/// often require these two paths to both be located on the same filesystem.
|
||||
|
3
third_party/rust/tokio/src/fs/metadata.rs
vendored
3
third_party/rust/tokio/src/fs/metadata.rs
vendored
@ -7,7 +7,7 @@ use std::path::Path;
|
||||
/// Given a path, queries the file system to get information about a file,
|
||||
/// directory, etc.
|
||||
///
|
||||
/// This is an async version of [`std::fs::metadata`][std]
|
||||
/// This is an async version of [`std::fs::metadata`].
|
||||
///
|
||||
/// This function will traverse symbolic links to query information about the
|
||||
/// destination file.
|
||||
@ -18,7 +18,6 @@ use std::path::Path;
|
||||
/// `GetFileAttributesEx` function on Windows. Note that, this [may change in
|
||||
/// the future][changes].
|
||||
///
|
||||
/// [std]: std::fs::metadata
|
||||
/// [changes]: https://doc.rust-lang.org/std/io/index.html#platform-specific-behavior
|
||||
///
|
||||
/// # Errors
|
||||
|
9
third_party/rust/tokio/src/fs/mocks.rs
vendored
9
third_party/rust/tokio/src/fs/mocks.rs
vendored
@ -30,6 +30,7 @@ mock! {
|
||||
pub fn open(pb: PathBuf) -> io::Result<Self>;
|
||||
pub fn set_len(&self, size: u64) -> io::Result<()>;
|
||||
pub fn set_permissions(&self, _perm: Permissions) -> io::Result<()>;
|
||||
pub fn set_max_buf_size(&self, max_buf_size: usize);
|
||||
pub fn sync_all(&self) -> io::Result<()>;
|
||||
pub fn sync_data(&self) -> io::Result<()>;
|
||||
pub fn try_clone(&self) -> io::Result<Self>;
|
||||
@ -124,12 +125,12 @@ impl<T> Future for JoinHandle<T> {
|
||||
type Output = Result<T, io::Error>;
|
||||
|
||||
fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
|
||||
use std::task::Poll::*;
|
||||
use std::task::Poll;
|
||||
|
||||
match Pin::new(&mut self.rx).poll(cx) {
|
||||
Ready(Ok(v)) => Ready(Ok(v)),
|
||||
Ready(Err(e)) => panic!("error = {:?}", e),
|
||||
Pending => Pending,
|
||||
Poll::Ready(Ok(v)) => Poll::Ready(Ok(v)),
|
||||
Poll::Ready(Err(e)) => panic!("error = {:?}", e),
|
||||
Poll::Pending => Poll::Pending,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
228
third_party/rust/tokio/src/fs/mod.rs
vendored
228
third_party/rust/tokio/src/fs/mod.rs
vendored
@ -1,46 +1,218 @@
|
||||
#![cfg(not(loom))]
|
||||
|
||||
//! Asynchronous file and standard stream adaptation.
|
||||
//! Asynchronous file utilities.
|
||||
//!
|
||||
//! This module contains utility methods and adapter types for input/output to
|
||||
//! files or standard streams (`Stdin`, `Stdout`, `Stderr`), and
|
||||
//! filesystem manipulation, for use within (and only within) a Tokio runtime.
|
||||
//! This module contains utility methods for working with the file system
|
||||
//! asynchronously. This includes reading/writing to files, and working with
|
||||
//! directories.
|
||||
//!
|
||||
//! Tasks run by *worker* threads should not block, as this could delay
|
||||
//! servicing reactor events. Portable filesystem operations are blocking,
|
||||
//! however. This module offers adapters which use a `blocking` annotation
|
||||
//! to inform the runtime that a blocking operation is required. When
|
||||
//! necessary, this allows the runtime to convert the current thread from a
|
||||
//! *worker* to a *backup* thread, where blocking is acceptable.
|
||||
//! Be aware that most operating systems do not provide asynchronous file system
|
||||
//! APIs. Because of that, Tokio will use ordinary blocking file operations
|
||||
//! behind the scenes. This is done using the [`spawn_blocking`] threadpool to
|
||||
//! run them in the background.
|
||||
//!
|
||||
//! ## Usage
|
||||
//! The `tokio::fs` module should only be used for ordinary files. Trying to use
|
||||
//! it with e.g., a named pipe on Linux can result in surprising behavior,
|
||||
//! such as hangs during runtime shutdown. For special files, you should use a
|
||||
//! dedicated type such as [`tokio::net::unix::pipe`] or [`AsyncFd`] instead.
|
||||
//!
|
||||
//! Where possible, users should prefer the provided asynchronous-specific
|
||||
//! traits such as [`AsyncRead`], or methods returning a `Future` or `Poll`
|
||||
//! type. Adaptions also extend to traits like `std::io::Read` where methods
|
||||
//! return `std::io::Result`. Be warned that these adapted methods may return
|
||||
//! `std::io::ErrorKind::WouldBlock` if a *worker* thread can not be converted
|
||||
//! to a *backup* thread immediately.
|
||||
//! Currently, Tokio will always use [`spawn_blocking`] on all platforms, but it
|
||||
//! may be changed to use asynchronous file system APIs such as io_uring in the
|
||||
//! future.
|
||||
//!
|
||||
//! **Warning**: These adapters may create a large number of temporary tasks,
|
||||
//! especially when reading large files. When performing a lot of operations
|
||||
//! in one batch, it may be significantly faster to use [`spawn_blocking`]
|
||||
//! directly:
|
||||
//! # Usage
|
||||
//!
|
||||
//! The easiest way to use this module is to use the utility functions that
|
||||
//! operate on entire files:
|
||||
//!
|
||||
//! * [`tokio::fs::read`](fn@crate::fs::read)
|
||||
//! * [`tokio::fs::read_to_string`](fn@crate::fs::read_to_string)
|
||||
//! * [`tokio::fs::write`](fn@crate::fs::write)
|
||||
//!
|
||||
//! The two `read` functions reads the entire file and returns its contents.
|
||||
//! The `write` function takes the contents of the file and writes those
|
||||
//! contents to the file. It overwrites the existing file, if any.
|
||||
//!
|
||||
//! For example, to read the file:
|
||||
//!
|
||||
//! ```
|
||||
//! # async fn dox() -> std::io::Result<()> {
|
||||
//! let contents = tokio::fs::read_to_string("my_file.txt").await?;
|
||||
//!
|
||||
//! println!("File has {} lines.", contents.lines().count());
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! To overwrite the file:
|
||||
//!
|
||||
//! ```
|
||||
//! # async fn dox() -> std::io::Result<()> {
|
||||
//! let contents = "First line.\nSecond line.\nThird line.\n";
|
||||
//!
|
||||
//! tokio::fs::write("my_file.txt", contents.as_bytes()).await?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Using `File`
|
||||
//!
|
||||
//! The main type for interacting with files is [`File`]. It can be used to read
|
||||
//! from and write to a given file. This is done using the [`AsyncRead`] and
|
||||
//! [`AsyncWrite`] traits. This type is generally used when you want to do
|
||||
//! something more complex than just reading or writing the entire contents in
|
||||
//! one go.
|
||||
//!
|
||||
//! **Note:** It is important to use [`flush`] when writing to a Tokio
|
||||
//! [`File`]. This is because calls to `write` will return before the write has
|
||||
//! finished, and [`flush`] will wait for the write to finish. (The write will
|
||||
//! happen even if you don't flush; it will just happen later.) This is
|
||||
//! different from [`std::fs::File`], and is due to the fact that `File` uses
|
||||
//! `spawn_blocking` behind the scenes.
|
||||
//!
|
||||
//! For example, to count the number of lines in a file without loading the
|
||||
//! entire file into memory:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use tokio::fs::File;
|
||||
//! use std::io::{BufReader, BufRead};
|
||||
//! async fn count_lines(file: File) -> Result<usize, std::io::Error> {
|
||||
//! let file = file.into_std().await;
|
||||
//! tokio::task::spawn_blocking(move || {
|
||||
//! let line_count = BufReader::new(file).lines().count();
|
||||
//! Ok(line_count)
|
||||
//! }).await?
|
||||
//! use tokio::io::AsyncReadExt;
|
||||
//!
|
||||
//! # async fn dox() -> std::io::Result<()> {
|
||||
//! let mut file = File::open("my_file.txt").await?;
|
||||
//!
|
||||
//! let mut chunk = vec![0; 4096];
|
||||
//! let mut number_of_lines = 0;
|
||||
//! loop {
|
||||
//! let len = file.read(&mut chunk).await?;
|
||||
//! if len == 0 {
|
||||
//! // Length of zero means end of file.
|
||||
//! break;
|
||||
//! }
|
||||
//! for &b in &chunk[..len] {
|
||||
//! if b == b'\n' {
|
||||
//! number_of_lines += 1;
|
||||
//! }
|
||||
//! }
|
||||
//! }
|
||||
//!
|
||||
//! println!("File has {} lines.", number_of_lines);
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! For example, to write a file line-by-line:
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use tokio::fs::File;
|
||||
//! use tokio::io::AsyncWriteExt;
|
||||
//!
|
||||
//! # async fn dox() -> std::io::Result<()> {
|
||||
//! let mut file = File::create("my_file.txt").await?;
|
||||
//!
|
||||
//! file.write_all(b"First line.\n").await?;
|
||||
//! file.write_all(b"Second line.\n").await?;
|
||||
//! file.write_all(b"Third line.\n").await?;
|
||||
//!
|
||||
//! // Remember to call `flush` after writing!
|
||||
//! file.flush().await?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! ## Tuning your file IO
|
||||
//!
|
||||
//! Tokio's file uses [`spawn_blocking`] behind the scenes, and this has serious
|
||||
//! performance consequences. To get good performance with file IO on Tokio, it
|
||||
//! is recommended to batch your operations into as few `spawn_blocking` calls
|
||||
//! as possible.
|
||||
//!
|
||||
//! One example of this difference can be seen by comparing the two reading
|
||||
//! examples above. The first example uses [`tokio::fs::read`], which reads the
|
||||
//! entire file in a single `spawn_blocking` call, and then returns it. The
|
||||
//! second example will read the file in chunks using many `spawn_blocking`
|
||||
//! calls. This means that the second example will most likely be more expensive
|
||||
//! for large files. (Of course, using chunks may be necessary for very large
|
||||
//! files that don't fit in memory.)
|
||||
//!
|
||||
//! The following examples will show some strategies for this:
|
||||
//!
|
||||
//! When creating a file, write the data to a `String` or `Vec<u8>` and then
|
||||
//! write the entire file in a single `spawn_blocking` call with
|
||||
//! `tokio::fs::write`.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! # async fn dox() -> std::io::Result<()> {
|
||||
//! let mut contents = String::new();
|
||||
//!
|
||||
//! contents.push_str("First line.\n");
|
||||
//! contents.push_str("Second line.\n");
|
||||
//! contents.push_str("Third line.\n");
|
||||
//!
|
||||
//! tokio::fs::write("my_file.txt", contents.as_bytes()).await?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! Use [`BufReader`] and [`BufWriter`] to buffer many small reads or writes
|
||||
//! into a few large ones. This example will most likely only perform one
|
||||
//! `spawn_blocking` call.
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use tokio::fs::File;
|
||||
//! use tokio::io::{AsyncWriteExt, BufWriter};
|
||||
//!
|
||||
//! # async fn dox() -> std::io::Result<()> {
|
||||
//! let mut file = BufWriter::new(File::create("my_file.txt").await?);
|
||||
//!
|
||||
//! file.write_all(b"First line.\n").await?;
|
||||
//! file.write_all(b"Second line.\n").await?;
|
||||
//! file.write_all(b"Third line.\n").await?;
|
||||
//!
|
||||
//! // Due to the BufWriter, the actual write and spawn_blocking
|
||||
//! // call happens when you flush.
|
||||
//! file.flush().await?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! Manually use [`std::fs`] inside [`spawn_blocking`].
|
||||
//!
|
||||
//! ```no_run
|
||||
//! use std::fs::File;
|
||||
//! use std::io::{self, Write};
|
||||
//! use tokio::task::spawn_blocking;
|
||||
//!
|
||||
//! # async fn dox() -> std::io::Result<()> {
|
||||
//! spawn_blocking(move || {
|
||||
//! let mut file = File::create("my_file.txt")?;
|
||||
//!
|
||||
//! file.write_all(b"First line.\n")?;
|
||||
//! file.write_all(b"Second line.\n")?;
|
||||
//! file.write_all(b"Third line.\n")?;
|
||||
//!
|
||||
//! // Unlike Tokio's file, the std::fs file does
|
||||
//! // not need flush.
|
||||
//!
|
||||
//! io::Result::Ok(())
|
||||
//! }).await.unwrap()?;
|
||||
//! # Ok(())
|
||||
//! # }
|
||||
//! ```
|
||||
//!
|
||||
//! It's also good to be aware of [`File::set_max_buf_size`], which controls the
|
||||
//! maximum amount of bytes that Tokio's [`File`] will read or write in a single
|
||||
//! [`spawn_blocking`] call. The default is two megabytes, but this is subject
|
||||
//! to change.
|
||||
//!
|
||||
//! [`spawn_blocking`]: fn@crate::task::spawn_blocking
|
||||
//! [`AsyncRead`]: trait@crate::io::AsyncRead
|
||||
//! [`AsyncWrite`]: trait@crate::io::AsyncWrite
|
||||
//! [`BufReader`]: struct@crate::io::BufReader
|
||||
//! [`BufWriter`]: struct@crate::io::BufWriter
|
||||
//! [`tokio::net::unix::pipe`]: crate::net::unix::pipe
|
||||
//! [`AsyncFd`]: crate::io::unix::AsyncFd
|
||||
//! [`flush`]: crate::io::AsyncWriteExt::flush
|
||||
//! [`tokio::fs::read`]: fn@crate::fs::read
|
||||
|
||||
mod canonicalize;
|
||||
pub use self::canonicalize::canonicalize;
|
||||
|
@ -25,7 +25,7 @@ use std::os::windows::fs::OpenOptionsExt;
|
||||
/// Generally speaking, when using `OpenOptions`, you'll first call [`new`],
|
||||
/// then chain calls to methods to set each option, then call [`open`], passing
|
||||
/// the path of the file you're trying to open. This will give you a
|
||||
/// [`io::Result`][result] with a [`File`] inside that you can further operate
|
||||
/// [`io::Result`] with a [`File`] inside that you can further operate
|
||||
/// on.
|
||||
///
|
||||
/// This is a specialized version of [`std::fs::OpenOptions`] for usage from
|
||||
@ -36,11 +36,9 @@ use std::os::windows::fs::OpenOptionsExt;
|
||||
///
|
||||
/// [`new`]: OpenOptions::new
|
||||
/// [`open`]: OpenOptions::open
|
||||
/// [result]: std::io::Result
|
||||
/// [`File`]: File
|
||||
/// [`File::open`]: File::open
|
||||
/// [`File::create`]: File::create
|
||||
/// [`std::fs::OpenOptions`]: std::fs::OpenOptions
|
||||
///
|
||||
/// # Examples
|
||||
///
|
||||
@ -444,7 +442,6 @@ feature! {
|
||||
/// # Examples
|
||||
///
|
||||
/// ```no_run
|
||||
/// use libc;
|
||||
/// use tokio::fs::OpenOptions;
|
||||
/// use std::io;
|
||||
///
|
||||
|
@ -1,5 +1,5 @@
|
||||
#![allow(unreachable_pub)]
|
||||
//! Mock version of std::fs::OpenOptions;
|
||||
//! Mock version of `std::fs::OpenOptions`;
|
||||
use mockall::mock;
|
||||
|
||||
use crate::fs::mocks::MockFile;
|
||||
|
4
third_party/rust/tokio/src/fs/read.rs
vendored
4
third_party/rust/tokio/src/fs/read.rs
vendored
@ -4,9 +4,7 @@ use std::{io, path::Path};
|
||||
|
||||
/// Reads the entire contents of a file into a bytes vector.
|
||||
///
|
||||
/// This is an async version of [`std::fs::read`][std]
|
||||
///
|
||||
/// [std]: std::fs::read
|
||||
/// This is an async version of [`std::fs::read`].
|
||||
///
|
||||
/// This is a convenience function for using [`File::open`] and [`read_to_end`]
|
||||
/// with fewer imports and without an intermediate variable. It pre-allocates a
|
||||
|
5
third_party/rust/tokio/src/fs/read_dir.rs
vendored
5
third_party/rust/tokio/src/fs/read_dir.rs
vendored
@ -24,7 +24,7 @@ const CHUNK_SIZE: usize = 32;
|
||||
|
||||
/// Returns a stream over the entries within a directory.
|
||||
///
|
||||
/// This is an async version of [`std::fs::read_dir`](std::fs::read_dir)
|
||||
/// This is an async version of [`std::fs::read_dir`].
|
||||
///
|
||||
/// This operation is implemented by running the equivalent blocking
|
||||
/// operation on a separate thread pool using [`spawn_blocking`].
|
||||
@ -140,6 +140,7 @@ impl ReadDir {
|
||||
target_os = "illumos",
|
||||
target_os = "haiku",
|
||||
target_os = "vxworks",
|
||||
target_os = "aix",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
)))]
|
||||
@ -203,6 +204,7 @@ pub struct DirEntry {
|
||||
target_os = "illumos",
|
||||
target_os = "haiku",
|
||||
target_os = "vxworks",
|
||||
target_os = "aix",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
)))]
|
||||
@ -336,6 +338,7 @@ impl DirEntry {
|
||||
target_os = "illumos",
|
||||
target_os = "haiku",
|
||||
target_os = "vxworks",
|
||||
target_os = "aix",
|
||||
target_os = "nto",
|
||||
target_os = "vita",
|
||||
)))]
|
||||
|
4
third_party/rust/tokio/src/fs/read_link.rs
vendored
4
third_party/rust/tokio/src/fs/read_link.rs
vendored
@ -5,9 +5,7 @@ use std::path::{Path, PathBuf};
|
||||
|
||||
/// Reads a symbolic link, returning the file that the link points to.
|
||||
///
|
||||
/// This is an async version of [`std::fs::read_link`][std]
|
||||
///
|
||||
/// [std]: std::fs::read_link
|
||||
/// This is an async version of [`std::fs::read_link`].
|
||||
pub async fn read_link(path: impl AsRef<Path>) -> io::Result<PathBuf> {
|
||||
let path = path.as_ref().to_owned();
|
||||
asyncify(move || std::fs::read_link(path)).await
|
||||
|
2
third_party/rust/tokio/src/fs/remove_dir.rs
vendored
2
third_party/rust/tokio/src/fs/remove_dir.rs
vendored
@ -5,7 +5,7 @@ use std::path::Path;
|
||||
|
||||
/// Removes an existing, empty directory.
|
||||
///
|
||||
/// This is an async version of [`std::fs::remove_dir`](std::fs::remove_dir)
|
||||
/// This is an async version of [`std::fs::remove_dir`].
|
||||
pub async fn remove_dir(path: impl AsRef<Path>) -> io::Result<()> {
|
||||
let path = path.as_ref().to_owned();
|
||||
asyncify(move || std::fs::remove_dir(path)).await
|
||||
|
4
third_party/rust/tokio/src/fs/remove_file.rs
vendored
4
third_party/rust/tokio/src/fs/remove_file.rs
vendored
@ -9,9 +9,7 @@ use std::path::Path;
|
||||
/// depending on platform, other open file descriptors may prevent immediate
|
||||
/// removal).
|
||||
///
|
||||
/// This is an async version of [`std::fs::remove_file`][std]
|
||||
///
|
||||
/// [std]: std::fs::remove_file
|
||||
/// This is an async version of [`std::fs::remove_file`].
|
||||
pub async fn remove_file(path: impl AsRef<Path>) -> io::Result<()> {
|
||||
let path = path.as_ref().to_owned();
|
||||
asyncify(move || std::fs::remove_file(path)).await
|
||||
|
2
third_party/rust/tokio/src/fs/rename.rs
vendored
2
third_party/rust/tokio/src/fs/rename.rs
vendored
@ -8,7 +8,7 @@ use std::path::Path;
|
||||
///
|
||||
/// This will not work if the new name is on a different mount point.
|
||||
///
|
||||
/// This is an async version of [`std::fs::rename`](std::fs::rename)
|
||||
/// This is an async version of [`std::fs::rename`].
|
||||
pub async fn rename(from: impl AsRef<Path>, to: impl AsRef<Path>) -> io::Result<()> {
|
||||
let from = from.as_ref().to_owned();
|
||||
let to = to.as_ref().to_owned();
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user