-
-
Notifications
You must be signed in to change notification settings - Fork 45
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
Refactor utilities under Foundation.Process and CartonHelpers.Process and share implementations #477
Conversation
このbytesの違いが出るやつは、 |
手元は通ったな CIのLinuxも通ったな CIのmacはなんだ? |
これがダメっぽいな。 |
エラーの場合も転送しようとしてexitするのは問題がありそうだ。 |
お、手元で同じエラーにできた |
TERMの転送がうまくいってないな、直撃して死んでしまう
|
あ! |
SIGTERMを書くところを間違えてSIGKILLにしていた。
|
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.
self comment
let signalSource = DispatchSource.makeSignalSource(signal: signalNo) | ||
signalSource.setEventHandler { [self] in | ||
signalSource.cancel() | ||
kill(processIdentifier, signalNo) |
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.
ここが元々 interrupt
固定になっていました。
@@ -17,3 +20,28 @@ extension ProcessResult { | |||
return try utf8Output() | |||
} | |||
} | |||
|
|||
@discardableResult | |||
private func osSignal( |
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.
Process.signal
メソッドと Darwin.signal
が被るので、
リネームのためにラッパーを置きます。
ターゲットによって Darwin.
じゃなかったりするため。
let signalSource = DispatchSource.makeSignalSource(signal: signalNo) | ||
signalSource.setEventHandler { | ||
signalSource.cancel() | ||
self.signal(signalNo) |
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.
ここが元々 signal(SIGINT)
固定になっていました。
@@ -43,24 +43,23 @@ final class DevCommandTests: XCTestCase { | |||
// FIXME: Don't assume a specific port is available since it can be used by others or tests | |||
try await withFixture("EchoExecutable") { packageDirectory in | |||
let process = try swiftRunProcess( | |||
["carton", "dev", "--verbose", "--port", "8081", "--skip-auto-open"], | |||
["carton", "dev", "--verbose", "--port", "8080", "--skip-auto-open"], |
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.
ここなんですが、すぐ上の testWithNoArguments
がサーバーを閉じられていない場合に、
8080 でぶつかってくれた方が問題を発見できるので、8081から変えたいです。
|
||
// client delay... let the server start up | ||
let delay: Duration = .seconds(30) |
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.
最初の1回で30秒待つのは手元の開発で不便すぎるので、
3秒にして試行回数を増やします。
@@ -78,7 +77,7 @@ final class DevCommandTests: XCTestCase { | |||
func checkForExpectedContent(process: SwiftRunProcess, at url: String) async throws { | |||
defer { | |||
// end the process regardless of success | |||
process.process.signal(SIGTERM) | |||
process.process.signal(SIGINT) |
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.
swiftpm pluginを正しく貫通する SIGINT を使います。
try frontend.checkRun( | ||
printsLoadingMessage: false, | ||
didExit: { | ||
print("Bundle written in \(bundleDirectory)") |
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 didExit
is called regardless the process succeeded or failed, so the message is printed even though the frontend process failed.
Do we really need didExit
hook point? It might be unnecessary if we move the message printing to the frontend
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.
挙動を変えてしまっていますね、すみません。
何も考えずにロジックを維持しようとしましたが、たしかに先のコマンドが自分でメッセージを出せば良さそうです。やってみます。
@@ -129,7 +129,7 @@ struct CartonFrontendBundleCommand: AsyncParsableCommand { | |||
topLevelResourcePaths: resources | |||
) | |||
|
|||
terminal.write("Bundle generation finished successfully\n", inColor: .green, bold: true) |
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.
このメッセージをfrontendで出した後で、plugin側で改めてパスを出していたため、以下のようなメッセージになっていました。
...
Bundle generation finished successfully
Bundle written in Bundle
これを統合し、frontend側で成功メッセージと配置したパスを表示するようにして、
plugin側のメッセージを出すのはやめました。
以下のような出力になります。
...
Building for debugging...
[386/386] Linking carton-frontend
Build complete! (32.48s)
Building "app"
Right after building the main binary size is 7.67 MB
After stripping debug info the main binary size is 5.49 MB
Running...
wasm-opt -Os --enable-bulk-memory /Users/omochi/github/swiftwasm/carton/Tests/Fixtures/SandboxApp/Bundle/main.wasm -o /Users/omochi/github/swiftwasm/carton/Tests/Fixtures/SandboxApp/Bundle/main.wasm
`wasm-opt` process finished successfully
After stripping debug info the main binary size is 3.49 MB
Copying resources to /Users/omochi/github/swiftwasm/carton/Tests/Fixtures/SandboxApp/Bundle/JavaScriptKit_JavaScriptKit.resources
Copying resources to /Users/omochi/github/swiftwasm/carton/Tests/Fixtures/SandboxApp/Bundle/DevServerTestApp_app.resources
Creating symlink /Users/omochi/github/swiftwasm/carton/Tests/Fixtures/SandboxApp/Bundle/style.css
Bundle successfully generated at /Users/omochi/github/swiftwasm/carton/Tests/Fixtures/SandboxApp/Bundle
ファイルパスはフルで出るようにしました。
この修正に伴い、didExitコールバックは消しました。
forwardExit: Bool = false | ||
) throws { | ||
if printsLoadingMessage { | ||
print("Running \(try commandLine)") |
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.
ここですが、元コードだと stderr に出力して flush していたのですが、
普通に Swift.print
で良いと思いました。
frontendの他の部分でも進行状況メッセージは stdout に出ていますし。
@kateinoigakukun 指摘事項に対応しました |
早すぎて入れ違いになってしまった。 |
SwiftPMが SIGINT を転送するが SIGTERM は転送しない問題はここの実装っぽい
|
背景・課題
driver, plugin, test では Foundation.Process が使われています。
frontend, test では CartonHelpers(TSC).Process が使われています。
そして、driver と plugin と frontend の3箇所で、
それぞれ Process の拡張が行われています。
そのためプロジェクトを横断的に読み書きするのが難しくなっています。
同じことをやりたくても書き方が違ったり、
同じメソッド名なのに挙動が違ったりもするからです。
また、同じものが重複して実装されている部分もあります。
提案
このパッチではそういったユーティリティを整理して統一・共通化します。
TSC.Process
の拡張についてはCartonHelpers
モジュールに移動します。TSC.Process
と一緒に定義すれば良いからです。Foundation.Process
の拡張については、CartonCore
モジュールに移動します。CartonCore
はdriver, plugin の両方からアクセスできるモジュールとして最近定義されました。setSignalForwarding
の統一これは TSC と Foundation の両方で局所的に書かれているので、
どちらもメソッドとして定義します。
ついでにバグがあったので直します。
forwardTerminationSignals
の統一setSignalForwarding
をSIGINT
とSIGTERM
について設定する操作はよく出てくるので、このメソッド名で統一します。
なお、元々はこれに
terminationHandler
によるexit
の転送が書いてありましたが、これは削除しました。
waitUntilExit
と一緒に使っていて意味がなかったからです。waitUntilExit
はterminationHandler
の完了を待たないので、そもそもレースコンディションが起きていました。
waitUntilExit
の後で exit forward すれば十分で、その方が安定します。checkRun
の整理Foudation.Process
には static func なcheckRun
があります。一方で、通常の
run
をさまざまな準備とともに使っている場所もあります。この、さまざまな準備の処理は、ほとんど
checkRun
と被っています。そこで、instance func な
checkRun
を実装してから、static func な
checkRun
はそれを呼び出す形に書き換えます。また、
checkRun
の内部で使われているいくつかの処理は定型なので、これもメソッドとして切り出します。
具体的には、
forwardExit
とcheckNonZeroExit
を切り出しました。シグナル転送の改修
従来、シグナル転送のロジックでは、
SIGINTとSIGTERMを受け取って、サブプロセスに SIGINT を送る実装になっていました。
ユーザはターミナルからSIGTERMを送ったはずなのに、
プロセスはSIGINTを受け取るということが起きてしまうのでこれは良くないと思います。
SIGINT を受け取ったら SIGINT を転送し、
SIGTERM を受け取ったら SIGTERM を転送するのが良いと思います。
ただし、
$ swift package plugin
コマンドは、SIGINT の転送をするが SIGTERM は転送しないようでした。
これは別途、swiftpmの実装を確認する予定です。
テストコードの中に carton driver に対して SIGTERM を送信するロジックがあり、
これが先述の転送挙動と組み合わさっていたために、
これを修正したところうまく終了できませんでした。
そのため、テストコードは SIGINT を送信するように修正しました。