kubkon opened PR #1443 from yacc
to master
:
OK, so this PR is a bit of an experiment that came about somewhat itself
when I was looking at refactoring use ofRc<RefCell<Descriptor>>
inside
Entry
struct. I've noticed that since we've placedVirtualFile
on the
same level asOsHandle
andStdin
etc., we've ended up necessiitating
checks for different combinations such as "is a real OS resource being mixed
up with a virtual resource?", and if that was the case, we'd panic since
this was clearly not allowed (e.g., symlinking, or worse renaming).
Therefore, it seemed natural for virtual file to be on the same level
as _any_ OS handle (regardless of whether it's an actual file, socket,
or stdio handle). In other words, we should ideally envision the following
hierarchy:\-- OsHandle \-- OsFile -- Stdio \-- VirtualThis way, we can deal with the mix up at a level above which cleans up
our logic significantly.On the other hand, when looking through the
virtfs
, the trait approach
to some type that's a validHandle
grew on me, and I think this
is the way to go. And this is what this PR is proposing, a trait
Handle
which features enough functionality to make both virtual and
OS ops to work. Now, insideEntry
we can safely store something like
Rc<dyn Handle>
whereHandle
can downcast to eitherVirtualFile
or
VirtualDir
, orOsHandle
if its an actual OS resource. Note that
I've leftHandle
as one massive trait, but I reckon we could split
it up into several smaller traits, each dealing with some bit of WASI
functionality. I'm hoping this would perhaps make it easier to figure
out polyfilling between snapshots and the new upcoming ephemeral
snapshot since a lot of boilerplate functionality is now done as part
of theHandle
trait implementation.Next, I've redone the original
OsHandle
to be anOsFile
which
now stores a raw descriptor/handle (RawFd
/RawHandle
) inside a
Cell
so that we can handle interior mutability in an easy (read,
non-panicky) way. In order not to lose the perks of derefercing to
std::fs::File
, I've added a convenience traitAsFile
which
will takeOsFile
by reference (or the stdio handles) and create
a non-ownedManuallyDrop<File>
resource which can be passed around
and acted upon the way we'd normally do on&File
. This change of
course implies that we now have to worry about properly closing all
OS resources stored as part ofOsFile
, thus this type now implements
Drop
trait which essentially speaking moves the raw descriptor/handle
into aFile
and drops it.Finally, I've redone setting time info on relative paths on *nix using
the same approach as advocated in the virtual fs. Namely, we do an
openat
followed byfilestat_set_times
on the obtained descriptor.
This effectively removes the need for customfiletime
module in
yanix
. However, this does probably incur additional cost of at least
one additional syscall, and I haven't checked whether this approach
performs as expected on platforms such as NixOS which as far as I remember
had some weirdness todo with linkingutimensat
symbols, etc. Still,
this change is worth considering given that the implementation of
path_filestat_set_times
cleans up a lot, albeit with some additional
cost.Anyhow, lemme y'all know what you think!
PS, if anybody is wondering why the incoming branch is called
yacc
,
it stands for "yet another cleanup cleanup" simply because I was out
of ideas...
kubkon requested iximeow for a review on PR #1443.
kubkon requested sunfishcode and iximeow for a review on PR #1443.
kubkon assigned PR #1443 to alexcrichton.
kubkon unassigned PR #1443 to alexcrichton.
kubkon requested alexcrichton, sunfishcode and iximeow for a review on PR #1443.
kubkon updated PR #1443 from yacc
to master
:
OK, so this PR is a bit of an experiment that came about somewhat itself
when I was looking at refactoring use ofRc<RefCell<Descriptor>>
inside
Entry
struct. I've noticed that since we've placedVirtualFile
on the
same level asOsHandle
andStdin
etc., we've ended up necessiitating
checks for different combinations such as "is a real OS resource being mixed
up with a virtual resource?", and if that was the case, we'd panic since
this was clearly not allowed (e.g., symlinking, or worse renaming).
Therefore, it seemed natural for virtual file to be on the same level
as _any_ OS handle (regardless of whether it's an actual file, socket,
or stdio handle). In other words, we should ideally envision the following
hierarchy:\-- OsHandle \-- OsFile -- Stdio \-- VirtualThis way, we can deal with the mix up at a level above which cleans up
our logic significantly.On the other hand, when looking through the
virtfs
, the trait approach
to some type that's a validHandle
grew on me, and I think this
is the way to go. And this is what this PR is proposing, a trait
Handle
which features enough functionality to make both virtual and
OS ops to work. Now, insideEntry
we can safely store something like
Rc<dyn Handle>
whereHandle
can downcast to eitherVirtualFile
or
VirtualDir
, orOsHandle
if its an actual OS resource. Note that
I've leftHandle
as one massive trait, but I reckon we could split
it up into several smaller traits, each dealing with some bit of WASI
functionality. I'm hoping this would perhaps make it easier to figure
out polyfilling between snapshots and the new upcoming ephemeral
snapshot since a lot of boilerplate functionality is now done as part
of theHandle
trait implementation.Next, I've redone the original
OsHandle
to be anOsFile
which
now stores a raw descriptor/handle (RawFd
/RawHandle
) inside a
Cell
so that we can handle interior mutability in an easy (read,
non-panicky) way. In order not to lose the perks of derefercing to
std::fs::File
, I've added a convenience traitAsFile
which
will takeOsFile
by reference (or the stdio handles) and create
a non-ownedManuallyDrop<File>
resource which can be passed around
and acted upon the way we'd normally do on&File
. This change of
course implies that we now have to worry about properly closing all
OS resources stored as part ofOsFile
, thus this type now implements
Drop
trait which essentially speaking moves the raw descriptor/handle
into aFile
and drops it.Finally, I've redone setting time info on relative paths on *nix using
the same approach as advocated in the virtual fs. Namely, we do an
openat
followed byfilestat_set_times
on the obtained descriptor.
This effectively removes the need for customfiletime
module in
yanix
. However, this does probably incur additional cost of at least
one additional syscall, and I haven't checked whether this approach
performs as expected on platforms such as NixOS which as far as I remember
had some weirdness todo with linkingutimensat
symbols, etc. Still,
this change is worth considering given that the implementation of
path_filestat_set_times
cleans up a lot, albeit with some additional
cost.Anyhow, lemme y'all know what you think!
PS, if anybody is wondering why the incoming branch is called
yacc
,
it stands for "yet another cleanup cleanup" simply because I was out
of ideas...
kubkon updated PR #1443 from yacc
to master
:
OK, so this PR is a bit of an experiment that came about somewhat itself
when I was looking at refactoring use ofRc<RefCell<Descriptor>>
inside
Entry
struct. I've noticed that since we've placedVirtualFile
on the
same level asOsHandle
andStdin
etc., we've ended up necessiitating
checks for different combinations such as "is a real OS resource being mixed
up with a virtual resource?", and if that was the case, we'd panic since
this was clearly not allowed (e.g., symlinking, or worse renaming).
Therefore, it seemed natural for virtual file to be on the same level
as _any_ OS handle (regardless of whether it's an actual file, socket,
or stdio handle). In other words, we should ideally envision the following
hierarchy:\-- OsHandle \-- OsFile -- Stdio \-- VirtualThis way, we can deal with the mix up at a level above which cleans up
our logic significantly.On the other hand, when looking through the
virtfs
, the trait approach
to some type that's a validHandle
grew on me, and I think this
is the way to go. And this is what this PR is proposing, a trait
Handle
which features enough functionality to make both virtual and
OS ops to work. Now, insideEntry
we can safely store something like
Rc<dyn Handle>
whereHandle
can downcast to eitherVirtualFile
or
VirtualDir
, orOsHandle
if its an actual OS resource. Note that
I've leftHandle
as one massive trait, but I reckon we could split
it up into several smaller traits, each dealing with some bit of WASI
functionality. I'm hoping this would perhaps make it easier to figure
out polyfilling between snapshots and the new upcoming ephemeral
snapshot since a lot of boilerplate functionality is now done as part
of theHandle
trait implementation.Next, I've redone the original
OsHandle
to be anOsFile
which
now stores a raw descriptor/handle (RawFd
/RawHandle
) inside a
Cell
so that we can handle interior mutability in an easy (read,
non-panicky) way. In order not to lose the perks of derefercing to
std::fs::File
, I've added a convenience traitAsFile
which
will takeOsFile
by reference (or the stdio handles) and create
a non-ownedManuallyDrop<File>
resource which can be passed around
and acted upon the way we'd normally do on&File
. This change of
course implies that we now have to worry about properly closing all
OS resources stored as part ofOsFile
, thus this type now implements
Drop
trait which essentially speaking moves the raw descriptor/handle
into aFile
and drops it.Finally, I've redone setting time info on relative paths on *nix using
the same approach as advocated in the virtual fs. Namely, we do an
openat
followed byfilestat_set_times
on the obtained descriptor.
This effectively removes the need for customfiletime
module in
yanix
. However, this does probably incur additional cost of at least
one additional syscall, and I haven't checked whether this approach
performs as expected on platforms such as NixOS which as far as I remember
had some weirdness todo with linkingutimensat
symbols, etc. Still,
this change is worth considering given that the implementation of
path_filestat_set_times
cleans up a lot, albeit with some additional
cost.Anyhow, lemme y'all know what you think!
PS, if anybody is wondering why the incoming branch is called
yacc
,
it stands for "yet another cleanup cleanup" simply because I was out
of ideas...
pchickey submitted PR Review.
pchickey submitted PR Review.
pchickey created PR Review Comment:
left in some commented out debugs here and just below
alexcrichton submitted PR Review.
kubkon updated PR #1443 from yacc
to master
:
OK, so this PR is a bit of an experiment that came about somewhat itself
when I was looking at refactoring use ofRc<RefCell<Descriptor>>
inside
Entry
struct. I've noticed that since we've placedVirtualFile
on the
same level asOsHandle
andStdin
etc., we've ended up necessiitating
checks for different combinations such as "is a real OS resource being mixed
up with a virtual resource?", and if that was the case, we'd panic since
this was clearly not allowed (e.g., symlinking, or worse renaming).
Therefore, it seemed natural for virtual file to be on the same level
as _any_ OS handle (regardless of whether it's an actual file, socket,
or stdio handle). In other words, we should ideally envision the following
hierarchy:\-- OsHandle \-- OsFile -- Stdio \-- VirtualThis way, we can deal with the mix up at a level above which cleans up
our logic significantly.On the other hand, when looking through the
virtfs
, the trait approach
to some type that's a validHandle
grew on me, and I think this
is the way to go. And this is what this PR is proposing, a trait
Handle
which features enough functionality to make both virtual and
OS ops to work. Now, insideEntry
we can safely store something like
Rc<dyn Handle>
whereHandle
can downcast to eitherVirtualFile
or
VirtualDir
, orOsHandle
if its an actual OS resource. Note that
I've leftHandle
as one massive trait, but I reckon we could split
it up into several smaller traits, each dealing with some bit of WASI
functionality. I'm hoping this would perhaps make it easier to figure
out polyfilling between snapshots and the new upcoming ephemeral
snapshot since a lot of boilerplate functionality is now done as part
of theHandle
trait implementation.Next, I've redone the original
OsHandle
to be anOsFile
which
now stores a raw descriptor/handle (RawFd
/RawHandle
) inside a
Cell
so that we can handle interior mutability in an easy (read,
non-panicky) way. In order not to lose the perks of derefercing to
std::fs::File
, I've added a convenience traitAsFile
which
will takeOsFile
by reference (or the stdio handles) and create
a non-ownedManuallyDrop<File>
resource which can be passed around
and acted upon the way we'd normally do on&File
. This change of
course implies that we now have to worry about properly closing all
OS resources stored as part ofOsFile
, thus this type now implements
Drop
trait which essentially speaking moves the raw descriptor/handle
into aFile
and drops it.Finally, I've redone setting time info on relative paths on *nix using
the same approach as advocated in the virtual fs. Namely, we do an
openat
followed byfilestat_set_times
on the obtained descriptor.
This effectively removes the need for customfiletime
module in
yanix
. However, this does probably incur additional cost of at least
one additional syscall, and I haven't checked whether this approach
performs as expected on platforms such as NixOS which as far as I remember
had some weirdness todo with linkingutimensat
symbols, etc. Still,
this change is worth considering given that the implementation of
path_filestat_set_times
cleans up a lot, albeit with some additional
cost.Anyhow, lemme y'all know what you think!
PS, if anybody is wondering why the incoming branch is called
yacc
,
it stands for "yet another cleanup cleanup" simply because I was out
of ideas...
iximeow submitted PR Review.
iximeow submitted PR Review.
iximeow created PR Review Comment:
Why the
+ 'static
here? My understanding of the interaction between lifetimes/trait objects is kind of fuzzy, but isn't'static
the implied default? (I'm not sure why we'd want to forbid non-'static
, either)
iximeow created PR Review Comment:
What _is_ the
TODO
here? Theget_file_type() == Err
case?
iximeow created PR Review Comment:
update_from
on anOsFile
that has adir
withSome
would then have a staledir
. I'm not sure how much an issue this actually is, since we onlyupdate_from
infdstat_set_flags
. Flags are on the referenced filesystem entry, not on thefd
, right? So inconsistent flags aren't actually possible? Otherwise we might end up in a state wheredir
was populated can iterate when it shouldn't, or can't iterate when it should.At the very least, if this is sound (and I suspect it is), I think it'd be good to have a comment describing why alongside this impl.
iximeow created PR Review Comment:
ReOpenFile
requires the file handle came fromCreateFile
, but the standard library will useGetStdHandle
rather thanCreateFile("CONIN$",...
orCONOUT$
. If it works I'd be a little suspect of it mysteriously breaking one day. Judging by https://github.com/rust-lang/rust/issues/40490 (found when looking to confirm how stdlib deals with Windows stdio) it seems pretty suspect to retain a stdio handle in the first place?Nothing specific to add, just topical thought meandering, sorry :sweat_smile:
pchickey submitted PR Review.
pchickey created PR Review Comment:
That syntax threw me off when I learned it a week or two ago, it just means that the
Handle
concrete type cant have a lifetime.
kubkon submitted PR Review.
kubkon created PR Review Comment:
Yep, exactly as @pchickey said. I can't foresee a situation where type that implements
Handle
wouldn't last for the entire duration of the program.
kubkon submitted PR Review.
kubkon created PR Review Comment:
Oh right, I forgot to remove it. Thanks for spotting this one!
kubkon created PR Review Comment:
That's an excellent observation, thanks! I think adding a comment to remember about this potential issue is the best thing to do here.
On a related albeit somewhat different note, I'd still like to refactor how we store the
DIR
stream pointer on BSDes inOsFile
. Having an embeddedOption
seems like a less than ideal solution to use here. I was actually thinking of splitting the type into two or possibly an enum, so that if we are dealing with a dir on BSD, we'd immediately store a validDIR
stream pointer. But this will be a subsequent PR :-)
kubkon submitted PR Review.
kubkon submitted PR Review.
kubkon created PR Review Comment:
Oh good find, thanks! So if I understood it right, modifying stdio should error out on Windows since the handle was obtained from
GetStdHandle
and notCreateFile
. I'm keen to leave some sort of TODO here anyway to investigate this further on Windows.
kubkon updated PR #1443 from yacc
to master
:
OK, so this PR is a bit of an experiment that came about somewhat itself
when I was looking at refactoring use ofRc<RefCell<Descriptor>>
inside
Entry
struct. I've noticed that since we've placedVirtualFile
on the
same level asOsHandle
andStdin
etc., we've ended up necessiitating
checks for different combinations such as "is a real OS resource being mixed
up with a virtual resource?", and if that was the case, we'd panic since
this was clearly not allowed (e.g., symlinking, or worse renaming).
Therefore, it seemed natural for virtual file to be on the same level
as _any_ OS handle (regardless of whether it's an actual file, socket,
or stdio handle). In other words, we should ideally envision the following
hierarchy:\-- OsHandle \-- OsFile -- Stdio \-- VirtualThis way, we can deal with the mix up at a level above which cleans up
our logic significantly.On the other hand, when looking through the
virtfs
, the trait approach
to some type that's a validHandle
grew on me, and I think this
is the way to go. And this is what this PR is proposing, a trait
Handle
which features enough functionality to make both virtual and
OS ops to work. Now, insideEntry
we can safely store something like
Rc<dyn Handle>
whereHandle
can downcast to eitherVirtualFile
or
VirtualDir
, orOsHandle
if its an actual OS resource. Note that
I've leftHandle
as one massive trait, but I reckon we could split
it up into several smaller traits, each dealing with some bit of WASI
functionality. I'm hoping this would perhaps make it easier to figure
out polyfilling between snapshots and the new upcoming ephemeral
snapshot since a lot of boilerplate functionality is now done as part
of theHandle
trait implementation.Next, I've redone the original
OsHandle
to be anOsFile
which
now stores a raw descriptor/handle (RawFd
/RawHandle
) inside a
Cell
so that we can handle interior mutability in an easy (read,
non-panicky) way. In order not to lose the perks of derefercing to
std::fs::File
, I've added a convenience traitAsFile
which
will takeOsFile
by reference (or the stdio handles) and create
a non-ownedManuallyDrop<File>
resource which can be passed around
and acted upon the way we'd normally do on&File
. This change of
course implies that we now have to worry about properly closing all
OS resources stored as part ofOsFile
, thus this type now implements
Drop
trait which essentially speaking moves the raw descriptor/handle
into aFile
and drops it.Finally, I've redone setting time info on relative paths on *nix using
the same approach as advocated in the virtual fs. Namely, we do an
openat
followed byfilestat_set_times
on the obtained descriptor.
This effectively removes the need for customfiletime
module in
yanix
. However, this does probably incur additional cost of at least
one additional syscall, and I haven't checked whether this approach
performs as expected on platforms such as NixOS which as far as I remember
had some weirdness todo with linkingutimensat
symbols, etc. Still,
this change is worth considering given that the implementation of
path_filestat_set_times
cleans up a lot, albeit with some additional
cost.Anyhow, lemme y'all know what you think!
PS, if anybody is wondering why the incoming branch is called
yacc
,
it stands for "yet another cleanup cleanup" simply because I was out
of ideas...
kubkon updated PR #1443 from yacc
to master
:
OK, so this PR is a bit of an experiment that came about somewhat itself
when I was looking at refactoring use ofRc<RefCell<Descriptor>>
inside
Entry
struct. I've noticed that since we've placedVirtualFile
on the
same level asOsHandle
andStdin
etc., we've ended up necessiitating
checks for different combinations such as "is a real OS resource being mixed
up with a virtual resource?", and if that was the case, we'd panic since
this was clearly not allowed (e.g., symlinking, or worse renaming).
Therefore, it seemed natural for virtual file to be on the same level
as _any_ OS handle (regardless of whether it's an actual file, socket,
or stdio handle). In other words, we should ideally envision the following
hierarchy:\-- OsHandle \-- OsFile -- Stdio \-- VirtualThis way, we can deal with the mix up at a level above which cleans up
our logic significantly.On the other hand, when looking through the
virtfs
, the trait approach
to some type that's a validHandle
grew on me, and I think this
is the way to go. And this is what this PR is proposing, a trait
Handle
which features enough functionality to make both virtual and
OS ops to work. Now, insideEntry
we can safely store something like
Rc<dyn Handle>
whereHandle
can downcast to eitherVirtualFile
or
VirtualDir
, orOsHandle
if its an actual OS resource. Note that
I've leftHandle
as one massive trait, but I reckon we could split
it up into several smaller traits, each dealing with some bit of WASI
functionality. I'm hoping this would perhaps make it easier to figure
out polyfilling between snapshots and the new upcoming ephemeral
snapshot since a lot of boilerplate functionality is now done as part
of theHandle
trait implementation.Next, I've redone the original
OsHandle
to be anOsFile
which
now stores a raw descriptor/handle (RawFd
/RawHandle
) inside a
Cell
so that we can handle interior mutability in an easy (read,
non-panicky) way. In order not to lose the perks of derefercing to
std::fs::File
, I've added a convenience traitAsFile
which
will takeOsFile
by reference (or the stdio handles) and create
a non-ownedManuallyDrop<File>
resource which can be passed around
and acted upon the way we'd normally do on&File
. This change of
course implies that we now have to worry about properly closing all
OS resources stored as part ofOsFile
, thus this type now implements
Drop
trait which essentially speaking moves the raw descriptor/handle
into aFile
and drops it.Finally, I've redone setting time info on relative paths on *nix using
the same approach as advocated in the virtual fs. Namely, we do an
openat
followed byfilestat_set_times
on the obtained descriptor.
This effectively removes the need for customfiletime
module in
yanix
. However, this does probably incur additional cost of at least
one additional syscall, and I haven't checked whether this approach
performs as expected on platforms such as NixOS which as far as I remember
had some weirdness todo with linkingutimensat
symbols, etc. Still,
this change is worth considering given that the implementation of
path_filestat_set_times
cleans up a lot, albeit with some additional
cost.Anyhow, lemme y'all know what you think!
PS, if anybody is wondering why the incoming branch is called
yacc
,
it stands for "yet another cleanup cleanup" simply because I was out
of ideas...
kubkon merged PR #1443.
Last updated: Dec 23 2024 at 12:05 UTC