Skip to content
Draft
Next Next commit
WIP: PID, and resource / task info
  • Loading branch information
milseman committed Feb 5, 2021
commit ad80d0f9501063fa6f07862dbdf0404c4ea7faa7
16 changes: 16 additions & 0 deletions Sources/CSystem/include/CSystemDarwin.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
/*
This source file is part of the Swift System open source project

Copyright (c) 2020 Apple Inc. and the Swift System project authors
Licensed under Apache License v2.0 with Runtime Library Exception

See https://swift.org/LICENSE.txt for license information
*/

#ifdef __MACH__
#include "libproc.h"
#else
#error "whoops"
#endif

//
4 changes: 4 additions & 0 deletions Sources/CSystem/shims.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,3 +16,7 @@
#if defined(_WIN32)
#include <CSystemWindows.h>
#endif

#ifdef __MACH__
#include <CSystemDarwin.h>
#endif
1 change: 1 addition & 0 deletions Sources/System/Platform/Platform.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

@_implementationOnly import SystemInternals


// Public typealiases that can't be reexported from SystemInternals

/// The C `mode_t` type.
Expand Down
53 changes: 53 additions & 0 deletions Sources/System/Process/ProcessID.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@

// 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.
Copy link
Member

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. 🎉

Copy link
Contributor Author

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).

Copy link
Member

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.

//
import Darwin
extension CInterop {
public typealias PID = Int32
public typealias ProcTaskInfo = proc_taskinfo // FIXME
public typealias RUsageInfo = rusage_info_current // FIXME
Copy link
Member

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.

}

public struct ProcessID: RawRepresentable, Hashable, Codable {
Copy link

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.

Copy link
Contributor Author

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.

Copy link
Contributor

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).

/// The raw C process id.
@_alwaysEmitIntoClient
public let rawValue: CInterop.PID

/// Creates a strongly-typed process id from a raw C pid
@_alwaysEmitIntoClient
public init(rawValue: CInterop.PID) { self.rawValue = rawValue }

fileprivate init(_ rawValue: CInterop.PID) { self.init(rawValue: rawValue) }

}

extension ProcessID {
public struct TaskInfo: RawRepresentable/*, Hashable, Codable*/ {
/// The raw C process id.
@_alwaysEmitIntoClient
public let rawValue: CInterop.ProcTaskInfo

/// Creates a strongly-typed process id from a raw C pid
@_alwaysEmitIntoClient
public init(rawValue: CInterop.ProcTaskInfo) { self.rawValue = rawValue }

fileprivate init(_ rawValue: CInterop.ProcTaskInfo) { self.init(rawValue: rawValue) }

}

public struct ResourceUsageInfo: RawRepresentable/*, Hashable, Codable*/ {
/// The raw C process id.
@_alwaysEmitIntoClient
public let rawValue: CInterop.RUsageInfo

/// Creates a strongly-typed process id from a raw C pid
@_alwaysEmitIntoClient
public init(rawValue: CInterop.RUsageInfo) { self.rawValue = rawValue }

fileprivate init(_ rawValue: CInterop.RUsageInfo) { self.init(rawValue: rawValue) }

fileprivate static var blank: ResourceUsageInfo { ResourceUsageInfo(rusage_info_current()) }
}
}