-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DRAFT] ProcessID, Signal, SignalSet, TaskInfo, ResourceUsageInfo #20
base: main
Are you sure you want to change the base?
Conversation
|
||
// FIXME(DO NOT MERGE): We need to find a way around this. We want to declare | ||
// a typealias to a struct from a header, but don't want downstream to import | ||
// Darwin or the whole header just for that. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It turns out we should just import Darwin! Since System isn't an overlay, it doesn't need to reexport the module, and merely importing it won't pollute the client namespace with C junk. 🎉
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use Darwin
's types though? Also, can we do this with our CSystem
module as well (which is needed for Linux, since libC
isn't libSystem
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think so -- if people only import System, they will still be able to refer to these types by one of their System typealiases (such as the ones in CInterop or RawValue). (They can't spell Darwin.foo
unless they import it.)
CSystem
is trickier, because it shouldn't be a public module, so we should continue to import it @_implementationOnly
.
Sources/System/Process/Signal.swift
Outdated
public static var busError: Signal { Signal(SIGBUS) } | ||
|
||
/// SIGSEGV (11): segmentation violation (default behavior: create core image) | ||
public static var segfault: Signal { Signal(SIGSEGV) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Segfault is a colloquialism; segmentationFault
or segmentationViolation
seems like a better fit.
public static var segfault: Signal { Signal(SIGSEGV) } | |
public static var segmentationViolation: Signal { Signal(SIGSEGV) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not super how I feel about this. We're not using segmentation anymore but paging, so spelling "segfault" out may not make it easier to find?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having an unavailable-renamed entry for SIGSEGV
would hopefully help point to whatever name we choose.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true. But segmentationViolation
is still not what this will be sent for so I'd be inclined to leave the as a "term of art".
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is sort of like hangup
in that the name has somehow outlived its original meaning, which is now a complete anachronism. SIGSEGV is defined as "segmentation violation" in the man pages, so at least this expansion isn't likely to confuse anyone.
@weissi, what would you propose as a replacement? Note that System is supposed to follow the Swift naming conventions, so the original arbitrary abbreviations need to be replaced, no matter how well known.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
FWIW, POSIX describes SIGSEGV as "Invalid memory reference". Would we be willing to name it invalidMemoryReference
?
SEGV is such an (in)famous signal, it may be worth spending a term-of-art card on segmentationViolation
, no matter how far it is from the current meaning...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
invalidMemoryReference
is IMHO much better than segmentationViolation
. Both names however aren't as good as SIGSEGV
or sigsegv
IMHO. If you want to program your operating system directly, I think any translation of names is counterproductive and will lead to avoidable bugs, imprecise reviews, etc.
extension CInterop { | ||
public typealias PID = Int32 | ||
public typealias ProcTaskInfo = proc_taskinfo // FIXME | ||
public typealias RUsageInfo = rusage_info_current // FIXME |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have the option to just go with the original type names here, but I think it's still nice to have these typealiases.
// FIXME: names | ||
extension ProcessID.ResourceUsageInfo { | ||
// FIXME: UUID proper type | ||
public typealias UUID = ( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Foundation already has a wrapper for uuid_t
-- perhaps we should investigate shrinking it into System.
public var uuid: UUID { rawValue.ri_uuid } | ||
|
||
/// `ri_user_time`: TBD | ||
public var userTime: UInt64 { rawValue.ri_user_time } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should specify units for all these dimensioned quantities, ideally at the type system level. Should these time intervals return whatever we end up using for timespec_t
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately the headers are not clear what even is here. It's like that ResourceUsageInfo
will be split off from this PR eventually.
} | ||
|
||
|
||
public struct SignalSet: Hashable, Codable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I wonder if Codable
conformance is a good idea here -- sigset_t
values aren't necessarily portable between platforms/architectures.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
They are definitely not. Neither are signal numbers, errno codes, or so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's true, they would have to be encoded/decoded as the string of function calls.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't suppose there is a portable/easy way to list the full contents of a signal set, is there? (If we had one, we could maybe add Collection
and/or SetAlgebra
conformance. OTOH, that'd probably be gilding the lily...)
1 == withUnsafePointer { sigismember($0, sig.rawValue) } | ||
} | ||
|
||
public static var empty: SignalSet { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We should also provide a no-argument initializer that creates the empty set.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
random drive by
Sources/System/Process/Signal.swift
Outdated
public static var badSyscall: Signal { Signal(SIGSYS) } | ||
|
||
/// SIGPIPE (13): write on a pipe with no reader (default behavior: terminate process) | ||
public static var pipe: Signal { Signal(SIGPIPE) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
hmm, you can also get them on sockets...
public static var stop: Signal { Signal(SIGSTOP) } | ||
|
||
/// SIGTSTP (18): stop signal generated from keyboard (default behavior: stop process) | ||
public static var temporaryStop: Signal { Signal(SIGTSTP) } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think SIGSTOP
is uncatchable so it's not a request.
Co-authored-by: Karoy Lorentey <[email protected]>
Co-authored-by: Karoy Lorentey <[email protected]>
Co-authored-by: Karoy Lorentey <[email protected]>
Co-authored-by: Karoy Lorentey <[email protected]>
Co-authored-by: Karoy Lorentey <[email protected]>
Co-authored-by: Karoy Lorentey <[email protected]>
Co-authored-by: Karoy Lorentey <[email protected]>
Co-authored-by: Karoy Lorentey <[email protected]>
Co-authored-by: Karoy Lorentey <[email protected]>
public typealias RUsageInfo = rusage_info_current // FIXME | ||
} | ||
|
||
public struct ProcessID: RawRepresentable, Hashable, Codable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It seems to me that this is more of a Process
(i.e. a system object identified by a pid) than a ProcessID
- related APIs such as resource usage are really properties of the process more than the ID.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This struct is the handle to the process, it's very much like a file descriptor. It's not "safe" to assume it's still valid after a process is torn down, etc.
I've been thinking that a Process
type would probably be more like an actor
with interfaces for interprocess communication. Similarly with a proper File
type (though that might be a moveonly buffered struct). ProcessID
here is the lower-level systems model of that where we can communicate using descriptors or other forms of IPC.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think Process
will be part of SystemPackage
or layered on top? If it is part of SystemPackage
is there a way to make a stub Process
type so that this type could be Process.ID
? I'm not sure if this will work for ABI stability (though I also can't say that it won't), but maybe we can create an enum Process
that we then upgrade to an actor
(or whatever).
I think shipping this requires that we finish fleshing out |
} | ||
} | ||
return TaskInfo(result) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what the intended scope is for this pull request, but a common need is to get the path and name for a PID. proc_pidpath
and proc_name
.
Just a draft of low-level strongly typed wrappers for getting the current PID, querying usage information of a processes, and wrappers for signals and signal sets.