Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
google
GitHub Repository: google/crosvm
Path: blob/main/base/src/descriptor.rs
5394 views
1
// Copyright 2022 The ChromiumOS Authors
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
use std::fs::File;
6
use std::mem;
7
use std::mem::ManuallyDrop;
8
use std::sync::Arc;
9
10
use serde::Deserialize;
11
use serde::Serialize;
12
use serde::Serializer;
13
14
use crate::EventToken;
15
use crate::RawDescriptor;
16
17
/// Wraps a RawDescriptor and safely closes it when self falls out of scope.
18
#[derive(Serialize, Deserialize, Debug, Eq)]
19
#[serde(transparent)]
20
pub struct SafeDescriptor {
21
#[serde(with = "super::with_raw_descriptor")]
22
pub(crate) descriptor: RawDescriptor,
23
}
24
25
/// Trait for forfeiting ownership of the current raw descriptor, and returning the raw descriptor
26
pub trait IntoRawDescriptor {
27
fn into_raw_descriptor(self) -> RawDescriptor;
28
}
29
30
/// Trait for returning the underlying raw descriptor, without giving up ownership of the
31
/// descriptor.
32
pub trait AsRawDescriptor {
33
/// Returns the underlying raw descriptor.
34
///
35
/// Since the descriptor is still owned by the provider, callers should not assume that it will
36
/// remain open for longer than the immediate call of this method. In particular, it is a
37
/// dangerous practice to store the result of this method for future use: instead, it should be
38
/// used to e.g. obtain a raw descriptor that is immediately passed to a system call.
39
///
40
/// If you need to use the descriptor for a longer time (and particularly if you cannot reliably
41
/// track the lifetime of the providing object), you should probably consider using
42
/// [`SafeDescriptor`] (possibly along with [`trait@IntoRawDescriptor`]) to get full ownership
43
/// over a descriptor pointing to the same resource.
44
fn as_raw_descriptor(&self) -> RawDescriptor;
45
}
46
47
/// A trait similar to `AsRawDescriptor` but supports an arbitrary number of descriptors.
48
pub trait AsRawDescriptors {
49
/// Returns the underlying raw descriptors.
50
///
51
/// Please refer to the documentation of [`AsRawDescriptor::as_raw_descriptor`] for limitations
52
/// and recommended use.
53
fn as_raw_descriptors(&self) -> Vec<RawDescriptor>;
54
}
55
56
pub trait FromRawDescriptor {
57
/// # Safety
58
/// Safe only if the caller ensures nothing has access to the descriptor after passing it to
59
/// `from_raw_descriptor`
60
unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self;
61
}
62
63
impl AsRawDescriptor for SafeDescriptor {
64
fn as_raw_descriptor(&self) -> RawDescriptor {
65
self.descriptor
66
}
67
}
68
69
impl<T> AsRawDescriptor for Arc<T>
70
where
71
T: AsRawDescriptor,
72
{
73
fn as_raw_descriptor(&self) -> RawDescriptor {
74
self.as_ref().as_raw_descriptor()
75
}
76
}
77
78
impl<T> AsRawDescriptors for T
79
where
80
T: AsRawDescriptor,
81
{
82
fn as_raw_descriptors(&self) -> Vec<RawDescriptor> {
83
vec![self.as_raw_descriptor()]
84
}
85
}
86
87
impl IntoRawDescriptor for SafeDescriptor {
88
fn into_raw_descriptor(self) -> RawDescriptor {
89
let descriptor = self.descriptor;
90
mem::forget(self);
91
descriptor
92
}
93
}
94
95
impl FromRawDescriptor for SafeDescriptor {
96
unsafe fn from_raw_descriptor(descriptor: RawDescriptor) -> Self {
97
SafeDescriptor { descriptor }
98
}
99
}
100
101
impl TryFrom<&dyn AsRawDescriptor> for SafeDescriptor {
102
type Error = std::io::Error;
103
104
/// Clones the underlying descriptor (handle), internally creating a new descriptor.
105
///
106
/// WARNING: Windows does NOT support cloning/duplicating all types of handles. DO NOT use this
107
/// function on IO completion ports, sockets, or pseudo-handles (except those from
108
/// GetCurrentProcess or GetCurrentThread). See
109
/// <https://docs.microsoft.com/en-us/windows/win32/api/handleapi/nf-handleapi-duplicatehandle>
110
/// for further details.
111
///
112
/// TODO(b/191800567): this API has sharp edges on Windows. We should evaluate making some
113
/// adjustments to smooth those edges.
114
fn try_from(rd: &dyn AsRawDescriptor) -> std::result::Result<Self, Self::Error> {
115
// SAFETY:
116
// Safe because the underlying raw descriptor is guaranteed valid by rd's existence.
117
//
118
// Note that we are cloning the underlying raw descriptor since we have no guarantee of
119
// its existence after this function returns.
120
let rd_as_safe_desc = ManuallyDrop::new(unsafe {
121
SafeDescriptor::from_raw_descriptor(rd.as_raw_descriptor())
122
});
123
124
// We have to clone rd because we have no guarantee ownership was transferred (rd is
125
// borrowed).
126
rd_as_safe_desc
127
.try_clone()
128
.map_err(|e| Self::Error::from_raw_os_error(e.errno()))
129
}
130
}
131
132
impl From<File> for SafeDescriptor {
133
fn from(f: File) -> SafeDescriptor {
134
// SAFETY:
135
// Safe because we own the File at this point.
136
unsafe { SafeDescriptor::from_raw_descriptor(f.into_raw_descriptor()) }
137
}
138
}
139
140
/// For use cases where a simple wrapper around a [`RawDescriptor`] is needed, in order to e.g.
141
/// implement [`trait@AsRawDescriptor`].
142
///
143
/// This is a simply a wrapper and does not manage the lifetime of the descriptor. As such it is the
144
/// responsibility of the user to ensure that the wrapped descriptor will not be closed for as long
145
/// as the `Descriptor` is alive.
146
///
147
/// Most use-cases should prefer [`SafeDescriptor`] or implementing and using
148
/// [`trait@AsRawDescriptor`] on the type providing the descriptor. Using this wrapper usually means
149
/// something can be improved in your code.
150
///
151
/// Valid uses of this struct include:
152
/// * You only have a valid [`RawDescriptor`] and need to pass something that implements
153
/// [`trait@AsRawDescriptor`] to a function,
154
/// * You need to serialize a [`RawDescriptor`],
155
/// * You need [`trait@Send`] or [`trait@Sync`] for your descriptor and properly handle the case
156
/// where your descriptor gets closed.
157
///
158
/// Note that with the exception of the last use-case (which requires proper error checking against
159
/// the descriptor being closed), the `Descriptor` instance would be very short-lived.
160
#[derive(Copy, Clone, Debug, Hash, PartialEq, Eq, PartialOrd, Ord)]
161
#[repr(transparent)]
162
pub struct Descriptor(pub RawDescriptor);
163
impl AsRawDescriptor for Descriptor {
164
fn as_raw_descriptor(&self) -> RawDescriptor {
165
self.0
166
}
167
}
168
impl FromRawDescriptor for Descriptor {
169
unsafe fn from_raw_descriptor(desc: RawDescriptor) -> Self {
170
Descriptor(desc)
171
}
172
}
173
174
/// Implement token for implementations that wish to use this struct as such
175
impl EventToken for Descriptor {
176
fn as_raw_token(&self) -> u64 {
177
self.0 as u64
178
}
179
180
fn from_raw_token(data: u64) -> Self {
181
Descriptor(data as RawDescriptor)
182
}
183
}
184
185
impl Serialize for Descriptor {
186
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
187
where
188
S: Serializer,
189
{
190
serializer.serialize_u64(self.0 as u64)
191
}
192
}
193
194
impl<'de> Deserialize<'de> for Descriptor {
195
fn deserialize<D>(deserializer: D) -> Result<Descriptor, D::Error>
196
where
197
D: serde::Deserializer<'de>,
198
{
199
u64::deserialize(deserializer).map(|data| Descriptor(data as RawDescriptor))
200
}
201
}
202
203