Skip to content

Commit 2dcea87

Browse files
jun0claude
andcommitted
[rustjava-open-proposal-cards-triage-and-take-one] thread.rs 수동 span 을 래퍼로 분리 + 열린 카드 20장 재판정
- ThreadStartProxy::call = span 래퍼 · 본문은 inherent run() 으로 upstream 글자 그대로 복원 (대기 중 upstream 10커밋 대상 3-way: thread.rs 충돌 1 → 0) - 카드 17장 처분(해소 11 · 다른 repo/총괄 6) · 1장 채택 · 열린 카드 20 → 2 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
1 parent 0625c7e commit 2dcea87

3 files changed

Lines changed: 136 additions & 55 deletions

File tree

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
{
2+
"date": "2026-10-04",
3+
"taskId": "rustjava-open-proposal-cards-triage-and-take-one",
4+
"proposals": [],
5+
"adoptedProposals": [
6+
"2026-08-27-upstream-sync-s4#p1"
7+
],
8+
"declinedProposals": [
9+
"2026-08-27-upstream-sync-s4#p0",
10+
"2026-08-27-upstream-sync-squash-convergence#p0",
11+
"2026-09-03-upstream-sync-s5-s7-remeasure#p1",
12+
"2026-09-04-parity-sibling-repo-survey#p0",
13+
"2026-09-04-parity-sibling-repo-survey#p1",
14+
"2026-09-04-upstream-sync-s5#p1",
15+
"2026-09-04-upstream-sync-s6#p0",
16+
"2026-09-04-upstream-sync-s7#p0",
17+
"2026-09-04-upstream-sync-s8#p1",
18+
"2026-09-07-parity-per-repo-parser-axis-design#p1",
19+
"2026-09-07-parity-per-repo-parser-axis-design#p2",
20+
"2026-09-12-net-guard-subclass-fixture#p0",
21+
"2026-09-12-test-class-scratch-premise#p0",
22+
"2026-09-17-base-pull-and-stale-block-premise#p0",
23+
"2026-09-17-fixture-single-defect-audit#p0",
24+
"2026-09-17-fixture-version-table-backfill#p0",
25+
"2026-09-18-root-fixture-target-decision#p1"
26+
]
27+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
## [2026-10-04] 열린 제안 카드 20장 재판정 + thread.rs 수동 span 을 래퍼로 분리 (rustjava-open-proposal-cards-triage-and-take-one)
2+
3+
- 무엇을: 열린 카드 20장을 판정해 17장을 근거와 함께 내렸고(이미 해소 11 · 다른 repo·총괄 몫 6), `2026-08-27-upstream-sync-s4#p1` 1장을 채택해 `thread.rs` 의 수동 span 을 `ThreadStartProxy::call` 래퍼로 옮기고 본문(`run`)을 upstream 글자 그대로 되돌렸다. 남은 열린 카드는 2장이다.
4+
- 왜: 수동 span 이 본문 전체를 `async { … }.instrument(span)` 로 한 단 들여써서 upstream 이 본문 한 줄만 고쳐도 충돌했다(S1·S3·S4·S7·S8 다섯 번). 지금 대기 중인 upstream 10커밋도 본문 안 `put_field(…"alive"…)` 줄을 고친다.
5+
- 사용자 영향: 동작 변화 없음(같은 이름·필드의 span 이 같은 future 를 감싼다). 다음 upstream 동기 회차의 `thread.rs` 충돌이 1 → 0 이 된다.
6+
7+
## 실측 — 이번 변경이 충돌을 없앴는가
8+
9+
`git merge-file` 로 같은 3-way 를 두 번 쳤다(base = `merge-base HEAD upstream/main` · theirs = `upstream/main`, behind 10):
10+
11+
| ours | 충돌 hunk |
12+
|---|---|
13+
| `origin/main` 의 `thread.rs` | **1** |
14+
| 이 브랜치의 `thread.rs` | **0** |
15+
16+
이 브랜치 쪽 병합 결과와 `upstream/main` 의 차이는 `use tracing::Instrument;` 1줄과 span 래퍼 11줄(우리 고유분)뿐이다.
17+
`#[tracing::instrument]` 를 되살리지 않은 이유는 그대로다 — PR #4(tracing-attributes 가 no_std 를 깬다).
18+
19+
## 판정표
20+
21+
| 카드 | 판정 | 근거 |
22+
|---|---|---|
23+
| `2026-08-27-upstream-sync-s4#p0` (timer 시간 의존) | ⒜ 해소 | S5 가 upstream `c4665b06` 의 `test_timer.rs` 를 채택했다(`2026-09-04-upstream-sync-s5.md` §3). 테스트는 이제 `TestRuntime::advance_time`(`test-utils/src/lib.rs:139`, 가상 시계)으로 돌고 `test_timer_periodic` 은 없다 |
24+
| `2026-08-27-upstream-sync-s4#p1` (thread.rs span 이동) | ⒞ **채택** | 위 실측 |
25+
| `2026-08-27-upstream-sync-squash-convergence#p0` | ⒜ 해소 | `~/orchestrator/contracts/upstream-sync-repos.conf` 에 rustjava 등재 · `bin/queue-lint` 검사 22 가 `merge_strategy:` 선언을 강제한다 |
26+
| `2026-09-03-upstream-sync-s5-s7-remeasure#p1` | ⒜ 해소 | S5 가 `rustjava-upstream-sync-s5-with-remeasured-conflicts` 로 발권돼 string.rs 판단까지 끝냈다(`2026-09-04-upstream-sync-s5.md`) |
27+
| `2026-09-04-parity-sibling-repo-survey#p0` (wie +beta) | ⒝ wie | 넘길 곳 = wie 레인. 읽기만 해 본 결과 wie `AGENTS.md:70` 에 `cargo +beta clippy` 가 이미 있다 — 총괄이 닫힘 확인만 하면 된다 |
28+
| `2026-09-04-parity-sibling-repo-survey#p1` (qts ruff format) | ⒝ qts | 넘길 곳 = qts 레인. qts `Makefile:31` 에 `ruff format --check .` 가 이미 있다 — 같은 처리 |
29+
| `2026-09-04-upstream-sync-s5#p1` (충돌 목록 밖 파손) | ⒜ 해소 | `scripts/check-merge-dropped-symbols.py`(2026-09-18 · DoD·CI)가 «충돌 표시 없이 사라진 정의»를 잡는다. 서술자 어긋남은 그때처럼 `cargo test --all` 이 잡는다. 위험 서술은 `docs/upstream-sync-approach.md` §4 에 있다 |
30+
| `2026-09-04-upstream-sync-s6#p0` (S7 발권) | ⒜ 해소 | S7 착지(`2026-09-04-upstream-sync-s7.md`) |
31+
| `2026-09-04-upstream-sync-s7#p0` (S8 발권) | ⒜ 해소 | S8 착지, behind 12 → 0(`2026-09-04-upstream-sync-s8.md`) |
32+
| `2026-09-04-upstream-sync-s8#p1` (정기 축) | ⒜ 해소 | `2026-09-04-upstream-sync-cadence-decision.md`(PR #29 · `behind ≥ 20`) + `.github/workflows/upstream-behind.yml`(`2026-09-05-upstream-behind-scheduled-workflow.md`) |
33+
| `2026-09-07-parity-per-repo-parser-axis-design#p1` (qts 도달 가능성 락) | ⒝ qts | 넘길 곳 = qts 레인(`tests/guardrail/` · DoD) |
34+
| `2026-09-07-parity-per-repo-parser-axis-design#p2` (wie 천장 ③) | ⒝ wie | 넘길 곳 = wie 레인(`wie_cli/tests/support/dod_ci_parity.rs` `ceilings()`) |
35+
| `2026-09-12-net-guard-subclass-fixture#p0` (null 가드 축 종결 기록) | ⒜ 해소 | 기록 자체가 그 회차 워크로그 47행에 있다(「이 축에서 더 만들 티켓이 없다」) — 카드가 요구한 산출물이 이미 존재한다 |
36+
| `2026-09-12-test-class-scratch-premise#p0` (병렬 러너 시 픽스처별 cwd) | ⒜ 해소 | 전제가 `tests/test_class.rs:11-19` 주석에 적혀 있어 병렬 러너를 들이는 회차가 그 자리에서 읽는다. 병렬 러너 도입 계획은 없다(카드 스스로 «조건부») |
37+
| `2026-09-17-base-pull-and-stale-block-premise#p0` | ⒝ 총괄 | 넘길 곳 = orchestrator 발권 절차(차단 리포트의 head ↔ PR 현재 head 대조). 카드 target 자체가 «not this repo» |
38+
| `2026-09-17-fixture-single-defect-audit#p0` (상시 vs 1회) | ⒜ 해소 | `947fe90f` 가 결정했다 — `AGENTS.md` Testing Boundaries 에 «수동 · CI 는 돌리지 않는다»로 등재 |
39+
| `2026-09-17-fixture-version-table-backfill#p0` (새 규칙이 열린 PR 에 진 빚) | ⒝ 총괄 | 넘길 곳 = orchestrator 게이트③ 머지 템플릿(base pull 단계). 드러난 자리가 base pull 이고 그 단계는 이미 의무다 |
40+
| `2026-09-17-ldc-asm-regeneration-declined#p0` (ldc 양성 픽스처를 실 JVM 으로) | ⒞ 열림 유지 | `test-data/src/verify-javac-fixtures.sh` 에 ldc 줄이 아직 없다 |
41+
| `2026-09-18-root-fixture-target-decision#p0` (새 픽스처 target 규칙) | ⒞ 열림 유지 | `test-data/class-file-versions.txt` 머리가 «The rule for *new* fixtures is left open» 이라 적고 있다 |
42+
| `2026-09-18-root-fixture-target-decision#p1` (재개 조건 관찰자) | ⒜ 해소 | 대상 문서는 `947fe90f` 로 지워지고 조건이 `class-file-versions.txt` 머리로 접혔다. 남은 조건 셋 중 «동결이 사라짐»·«런타임이 major ≤52 를 버림»은 `test_fixture_pins`/`test_class` 가 red 로 알린다. 나머지 «다른 곳에 커버리지가 생김»은 결함이 아니라 판단이라 관찰자를 둘 것이 아니다 |
43+
44+
## 계수 (처분 후)
45+
46+
```
47+
$ python3 -c "...docs/next.md 의 명령 그대로..."
48+
2026-09-17-ldc-asm-regeneration-declined#p0
49+
2026-09-18-root-fixture-target-decision#p0
50+
```
51+
20 → **2**.

‎rustjava-runtime/src/classes/java/lang/thread.rs‎

Lines changed: 58 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -265,69 +265,72 @@ impl Thread {
265265
impl SpawnCallback for ThreadStartProxy {
266266
async fn call(&self) -> Result<()> {
267267
// manual span instead of #[tracing::instrument]: tracing-attributes breaks no_std
268-
// builds (tokio-rs/tracing#3388), and this was the only use in the workspace
268+
// builds (tokio-rs/tracing#3388), and this was the only use in the workspace.
269+
// The span lives in this wrapper so `run` below keeps upstream's text byte for byte
270+
// and upstream edits to it merge without conflict.
269271
let span = tracing::info_span!("java thread", id = self.thread_id);
272+
self.run().instrument(span).await
273+
}
274+
}
275+
276+
impl ThreadStartProxy {
277+
async fn run(&self) -> Result<()> {
278+
tracing::trace!("Thread start");
279+
280+
self.jvm.attach_thread(self.this.instance.clone()).await?;
281+
282+
let result: Result<()> = self.jvm.invoke_virtual(&self.this, "java/lang/Thread", "run", "()V", []).await;
283+
284+
if let Err(jvm::JavaError::JavaException(exception)) = &result {
285+
let trace = async {
286+
let string_writer = self.jvm.new_class("java/io/StringWriter", "()V", ()).await?;
287+
let print_writer = self
288+
.jvm
289+
.new_class("java/io/PrintWriter", "(Ljava/io/Writer;)V", (string_writer.clone(),))
290+
.await?;
291+
let _: () = self
292+
.jvm
293+
.invoke_virtual(
294+
exception,
295+
&exception.class_definition().name(),
296+
"printStackTrace",
297+
"(Ljava/io/PrintWriter;)V",
298+
(print_writer,),
299+
)
300+
.await?;
301+
let trace = self
302+
.jvm
303+
.invoke_virtual(&string_writer, "java/io/StringWriter", "toString", "()Ljava/lang/String;", [])
304+
.await?;
305+
JavaLangString::to_rust_string(&self.jvm, &trace).await
306+
}
307+
.await;
270308

271-
async {
272-
tracing::trace!("Thread start");
273-
274-
self.jvm.attach_thread(self.this.instance.clone()).await?;
275-
276-
let result: Result<()> = self.jvm.invoke_virtual(&self.this, "java/lang/Thread", "run", "()V", []).await;
277-
278-
if let Err(jvm::JavaError::JavaException(exception)) = &result {
279-
let trace = async {
280-
let string_writer = self.jvm.new_class("java/io/StringWriter", "()V", ()).await?;
281-
let print_writer = self
282-
.jvm
283-
.new_class("java/io/PrintWriter", "(Ljava/io/Writer;)V", (string_writer.clone(),))
284-
.await?;
285-
let _: () = self
286-
.jvm
287-
.invoke_virtual(
288-
exception,
289-
&exception.class_definition().name(),
290-
"printStackTrace",
291-
"(Ljava/io/PrintWriter;)V",
292-
(print_writer,),
293-
)
294-
.await?;
295-
let trace = self
296-
.jvm
297-
.invoke_virtual(&string_writer, "java/io/StringWriter", "toString", "()Ljava/lang/String;", [])
298-
.await?;
299-
JavaLangString::to_rust_string(&self.jvm, &trace).await
300-
}
301-
.await;
302-
303-
match trace {
304-
Ok(trace) => tracing::error!("Uncaught exception in thread {}:\n{}", self.thread_id, trace),
305-
Err(error) => tracing::error!(?error, "failed to format uncaught exception in thread {}", self.thread_id),
306-
}
309+
match trace {
310+
Ok(trace) => tracing::error!("Uncaught exception in thread {}:\n{}", self.thread_id, trace),
311+
Err(error) => tracing::error!(?error, "failed to format uncaught exception in thread {}", self.thread_id),
307312
}
313+
}
308314

309-
let mut this = (*self.this).clone();
310-
let cleanup = if let Err(error) = self.jvm.monitor_enter(&self.this).await {
311-
Err(error)
315+
let mut this = (*self.this).clone();
316+
let cleanup = if let Err(error) = self.jvm.monitor_enter(&self.this).await {
317+
Err(error)
318+
} else {
319+
let alive_result = self.jvm.put_field(&mut this, "alive", "Z", false).await;
320+
let notify_result = if alive_result.is_ok() {
321+
self.jvm.object_notify(&self.this, usize::MAX).await
312322
} else {
313-
let alive_result = self.jvm.put_field(&mut this, "alive", "Z", false).await;
314-
let notify_result = if alive_result.is_ok() {
315-
self.jvm.object_notify(&self.this, usize::MAX).await
316-
} else {
317-
Ok(())
318-
};
319-
let exit_result = self.jvm.monitor_exit(&self.this).await;
320-
alive_result.and(notify_result).and(exit_result)
323+
Ok(())
321324
};
322-
let detach_result = self.jvm.detach_thread();
325+
let exit_result = self.jvm.monitor_exit(&self.this).await;
326+
alive_result.and(notify_result).and(exit_result)
327+
};
328+
let detach_result = self.jvm.detach_thread();
323329

324-
cleanup?;
325-
detach_result?;
330+
cleanup?;
331+
detach_result?;
326332

327-
Ok(())
328-
}
329-
.instrument(span)
330-
.await
333+
Ok(())
331334
}
332335
}
333336

0 commit comments

Comments
 (0)