Import upstream changes of `TSC.Process` (#460)
This commit is contained in:
parent
bb9a91ce0b
commit
7613683095
|
@ -116,9 +116,23 @@ let package = Package(
|
|||
],
|
||||
exclude: ["Utilities/README.md"]
|
||||
),
|
||||
.target(
|
||||
/** Shim target to import missing C headers in Darwin and Glibc modulemap. */
|
||||
name: "TSCclibc",
|
||||
cSettings: [
|
||||
.define("_GNU_SOURCE", .when(platforms: [.linux])),
|
||||
]
|
||||
),
|
||||
.target(
|
||||
/** Cross-platform access to bare `libc` functionality. */
|
||||
name: "TSCLibc"
|
||||
),
|
||||
.target(
|
||||
name: "CartonHelpers",
|
||||
dependencies: [],
|
||||
dependencies: [
|
||||
"TSCclibc",
|
||||
"TSCLibc"
|
||||
],
|
||||
exclude: ["Basics/README.md"]
|
||||
),
|
||||
.target(name: "WebDriverClient", dependencies: []),
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,99 @@
|
|||
/*
|
||||
This source file is part of the Swift.org open source project
|
||||
|
||||
Copyright (c) 2014 - 2017 Apple Inc. and the Swift project authors
|
||||
Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
|
||||
See http://swift.org/LICENSE.txt for license information
|
||||
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
|
||||
*/
|
||||
|
||||
import Foundation
|
||||
#if os(Windows)
|
||||
import WinSDK
|
||||
#endif
|
||||
|
||||
/// This class bridges the gap between Darwin and Linux Foundation Threading API.
|
||||
/// It provides closure based execution and a join method to block the calling thread
|
||||
/// until the thread is finished executing.
|
||||
final public class Thread {
|
||||
|
||||
/// The thread implementation which is Foundation.Thread on Linux and
|
||||
/// a Thread subclass which provides closure support on Darwin.
|
||||
private var thread: ThreadImpl!
|
||||
|
||||
/// Condition variable to support blocking other threads using join when this thread has not finished executing.
|
||||
private var finishedCondition: Condition
|
||||
|
||||
/// A boolean variable to track if this thread has finished executing its task.
|
||||
private var isFinished: Bool
|
||||
|
||||
/// Creates an instance of thread class with closure to be executed when start() is called.
|
||||
public init(task: @escaping () -> Void) {
|
||||
isFinished = false
|
||||
finishedCondition = Condition()
|
||||
|
||||
// Wrap the task with condition notifying any other threads blocked due to this thread.
|
||||
// Capture self weakly to avoid reference cycle. In case Thread is deinited before the task
|
||||
// runs, skip the use of finishedCondition.
|
||||
let theTask = { [weak self] in
|
||||
if let strongSelf = self {
|
||||
precondition(!strongSelf.isFinished)
|
||||
strongSelf.finishedCondition.whileLocked {
|
||||
task()
|
||||
strongSelf.isFinished = true
|
||||
strongSelf.finishedCondition.broadcast()
|
||||
}
|
||||
} else {
|
||||
// If the containing thread has been destroyed, we can ignore the finished condition and just run the
|
||||
// task.
|
||||
task()
|
||||
}
|
||||
}
|
||||
|
||||
self.thread = ThreadImpl(block: theTask)
|
||||
}
|
||||
|
||||
/// Starts the thread execution.
|
||||
public func start() {
|
||||
thread.start()
|
||||
}
|
||||
|
||||
/// Blocks the calling thread until this thread is finished execution.
|
||||
public func join() {
|
||||
finishedCondition.whileLocked {
|
||||
while !isFinished {
|
||||
finishedCondition.wait()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Causes the calling thread to yield execution to another thread.
|
||||
public static func yield() {
|
||||
#if os(Windows)
|
||||
SwitchToThread()
|
||||
#else
|
||||
sched_yield()
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
#if canImport(Darwin)
|
||||
/// A helper subclass of Foundation's Thread with closure support.
|
||||
final private class ThreadImpl: Foundation.Thread {
|
||||
|
||||
/// The task to be executed.
|
||||
private let task: () -> Void
|
||||
|
||||
override func main() {
|
||||
task()
|
||||
}
|
||||
|
||||
init(block task: @escaping () -> Void) {
|
||||
self.task = task
|
||||
}
|
||||
}
|
||||
#else
|
||||
// Thread on Linux supports closure so just use it directly.
|
||||
typealias ThreadImpl = Foundation.Thread
|
||||
#endif
|
|
@ -809,7 +809,7 @@ private protocol _FileWatcher {
|
|||
let delegate: FSEventStreamDelegate
|
||||
|
||||
/// The thread on which the stream is running.
|
||||
private var thread: Thread?
|
||||
private var thread: Foundation.Thread?
|
||||
|
||||
/// The run loop attached to the stream.
|
||||
private var runLoop: CFRunLoop?
|
||||
|
@ -844,7 +844,7 @@ private protocol _FileWatcher {
|
|||
|
||||
// Start the runloop.
|
||||
public func start() throws {
|
||||
let thread = Thread { [weak self] in
|
||||
let thread = Foundation.Thread { [weak self] in
|
||||
guard let `self` = self else { return }
|
||||
self.runLoop = CFRunLoopGetCurrent()
|
||||
let queue = DispatchQueue(label: "org.swiftwasm.carton.FSWatch")
|
||||
|
|
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
This source file is part of the Swift.org open source project
|
||||
|
||||
Copyright (c) 2014 - 2020 Apple Inc. and the Swift project authors
|
||||
Licensed under Apache License v2.0 with Runtime Library Exception
|
||||
|
||||
See http://swift.org/LICENSE.txt for license information
|
||||
See http://swift.org/CONTRIBUTORS.txt for Swift project authors
|
||||
*/
|
||||
|
||||
#if canImport(Glibc)
|
||||
@_exported import Glibc
|
||||
#elseif canImport(Musl)
|
||||
@_exported import Musl
|
||||
#elseif os(Windows)
|
||||
@_exported import CRT
|
||||
@_exported import WinSDK
|
||||
#else
|
||||
@_exported import Darwin.C
|
||||
#endif
|
||||
|
||||
#if os(Windows)
|
||||
private func __randname(_ buffer: UnsafeMutablePointer<CChar>) {
|
||||
let alpha = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||
_ = (0 ..< 6).map { index in
|
||||
buffer[index] = CChar(alpha.shuffled().randomElement()!.utf8.first!)
|
||||
}
|
||||
}
|
||||
|
||||
// char *mkdtemp(char *template);
|
||||
// NOTE(compnerd) this is unsafe! This assumes that the template is *ASCII*.
|
||||
public func mkdtemp(
|
||||
_ template: UnsafeMutablePointer<CChar>?
|
||||
) -> UnsafeMutablePointer<CChar>? {
|
||||
// Although the signature of the function is `char *(*)(char *)`, the C
|
||||
// library treats it as `char *(*)(char * _Nonull)`. Most implementations
|
||||
// will simply use and trigger a segmentation fault on x86 (and similar faults
|
||||
// on other architectures) when the memory is accessed. This roughly emulates
|
||||
// that by terminating in the case even though it is possible for us to return
|
||||
// an error.
|
||||
guard let template = template else { fatalError() }
|
||||
|
||||
let length: Int = strlen(template)
|
||||
|
||||
// Validate the precondition: the template must terminate with 6 `X` which
|
||||
// will be filled in to generate a unique directory.
|
||||
guard length >= 6, memcmp(template + length - 6, "XXXXXX", 6) == 0 else {
|
||||
_set_errno(EINVAL)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Attempt to create the directory
|
||||
var retries: Int = 100
|
||||
repeat {
|
||||
__randname(template + length - 6)
|
||||
if _mkdir(template) == 0 {
|
||||
return template
|
||||
}
|
||||
retries = retries - 1
|
||||
} while retries > 0
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// int mkstemps(char *template, int suffixlen);
|
||||
public func mkstemps(
|
||||
_ template: UnsafeMutablePointer<CChar>?,
|
||||
_ suffixlen: Int32
|
||||
) -> Int32 {
|
||||
// Although the signature of the function is `char *(*)(char *)`, the C
|
||||
// library treats it as `char *(*)(char * _Nonull)`. Most implementations
|
||||
// will simply use and trigger a segmentation fault on x86 (and similar faults
|
||||
// on other architectures) when the memory is accessed. This roughly emulates
|
||||
// that by terminating in the case even though it is possible for us to return
|
||||
// an error.
|
||||
guard let template = template else { fatalError() }
|
||||
|
||||
let length: Int = strlen(template)
|
||||
|
||||
// Validate the precondition: the template must terminate with 6 `X` which
|
||||
// will be filled in to generate a unique directory.
|
||||
guard length >= 6, memcmp(template + length - Int(suffixlen) - 6, "XXXXXX", 6) == 0 else {
|
||||
_set_errno(EINVAL)
|
||||
return -1
|
||||
}
|
||||
|
||||
// Attempt to create file
|
||||
var retries: Int = 100
|
||||
repeat {
|
||||
__randname(template + length - Int(suffixlen) - 6)
|
||||
var fd: CInt = -1
|
||||
if _sopen_s(&fd, template, _O_RDWR | _O_CREAT | _O_BINARY | _O_NOINHERIT,
|
||||
_SH_DENYNO, _S_IREAD | _S_IWRITE) == 0 {
|
||||
return fd
|
||||
}
|
||||
retries = retries - 1
|
||||
} while retries > 0
|
||||
|
||||
return -1
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,21 @@
|
|||
#if defined(__linux__)
|
||||
#include <sys/inotify.h>
|
||||
#endif
|
||||
|
||||
#define STR_EXPAND(VALUE) #VALUE
|
||||
#define STR(VALUE) STR_EXPAND(VALUE)
|
||||
|
||||
static inline const char* SPM_VendorNameString() {
|
||||
#ifdef SPM_VENDOR_NAME
|
||||
return STR(SPM_VENDOR_NAME);
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
static inline const char* SPM_BuildIdentifierString() {
|
||||
#ifdef SPM_BUILD_IDENT
|
||||
return STR(SPM_BUILD_IDENT);
|
||||
#else
|
||||
return "";
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,5 @@
|
|||
module TSCclibc {
|
||||
header "TSCclibc.h"
|
||||
header "process.h"
|
||||
export *
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
#if defined(__linux__)
|
||||
|
||||
#include <spawn.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// Wrapper method for posix_spawn_file_actions_addchdir_np that fails on Linux versions that do not have this method available.
|
||||
int SPM_posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t *restrict file_actions, const char *restrict path);
|
||||
|
||||
// Runtime check for the availability of posix_spawn_file_actions_addchdir_np. Returns 0 if the method is available, -1 if not.
|
||||
bool SPM_posix_spawn_file_actions_addchdir_np_supported();
|
||||
|
||||
#endif
|
|
@ -0,0 +1,35 @@
|
|||
#if defined(__linux__)
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE /* for posix_spawn_file_actions_addchdir_np */
|
||||
#endif
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
#include "process.h"
|
||||
|
||||
int SPM_posix_spawn_file_actions_addchdir_np(posix_spawn_file_actions_t *restrict file_actions, const char *restrict path) {
|
||||
#if defined(__GLIBC__)
|
||||
# if __GLIBC_PREREQ(2, 29)
|
||||
return posix_spawn_file_actions_addchdir_np(file_actions, path);
|
||||
# else
|
||||
return ENOSYS;
|
||||
# endif
|
||||
#else
|
||||
return ENOSYS;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SPM_posix_spawn_file_actions_addchdir_np_supported() {
|
||||
#if defined(__GLIBC__)
|
||||
# if __GLIBC_PREREQ(2, 29)
|
||||
return true;
|
||||
# else
|
||||
return false;
|
||||
# endif
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue