yamine 0.21.0 → 0.21.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 73d2fe319b2c8af2c4bf821285dc76af42705e532761a8b2351377696928a114
4
- data.tar.gz: 5a92b4760142642deed0a5a0131536094ac553b79759924daa7cc2157dec90a6
3
+ metadata.gz: 8e920f5f6d29a92e0a6e81ca671bccf62e0a264ec453f9b5bc4d42d4e56980d3
4
+ data.tar.gz: cc06342930ee7c882cf30fd2818f1a60495c8a59e44ec6779cc666f569493ac0
5
5
  SHA512:
6
- metadata.gz: 859e65d51d8e417cb1c747cf2d95a8336d4266fd57347d611ca3744baf4538dde86190fc5bc46023cbf28a0c12faceb7d2e3f84895afd62617e2c78e7fd1fc46
7
- data.tar.gz: 8fc48c3d08d4ef3dfb5f579f41583ce3f315c90e896289279b072a5f9e6d66013eaa2b02f66eeb8ce3e983d2d4664287aa3e868e33606bc4f687f7975cd9c25a
6
+ metadata.gz: 4164dabf9bd5537023ad59d426a958a5e284a90f0226cc83e0533cf635edf0c65acc16dd311d58a88df83d7abdcdfb92034703ecda06d89af08bb5ec96c73635
7
+ data.tar.gz: 1e3af2b55e54885fe8aeed98856c4371eab280ec981cd2644ebb75aba0206752ae44307c0252f51188a778426efbb882ef2285c63f142def39f4e876f77302d6
data/CHANGELOG.md CHANGED
@@ -2,6 +2,27 @@
2
2
 
3
3
  ## [Unreleased]
4
4
 
5
+ ## [0.21.1] — 2026-09-29
6
+
7
+ ### Fixed
8
+
9
+ - **Claiming a per-worktree database no longer raises `NoMethodError`
10
+ on Ruby 3.2/3.3.** The claim stamps the state file with
11
+ `Time#iso8601`, but `lib/yamine/database.rb` never required the
12
+ stdlib `time` library, and on 3.2/3.3 nothing else loads it
13
+ implicitly — so every claim raised (34 unit errors on those rubies
14
+ in CI). 0.21.0 is affected. One `require "time"`, alongside the
15
+ stdlibs that file already pulls in.
16
+ - **A closed WebSocket upgrade no longer leaks a thread on Linux.**
17
+ `pipe_both` tore each end down with `close` from the sibling
18
+ thread, and a close from another thread does not interrupt that
19
+ copy's blocking read on Linux (it does on macOS) — so every closed
20
+ upgrade parked a thread forever, `handle` never unwound, and they
21
+ accumulated in the root daemon. Teardown is now symmetric
22
+ `shutdown(2)`, which wakes the parked read with EOF; both sockets
23
+ still close exactly once, and no timeout was added to the
24
+ unbounded upgrade path.
25
+
5
26
  ## [0.21.0] — 2026-09-28
6
27
 
7
28
  ### Security
data/README.md CHANGED
@@ -508,10 +508,11 @@ bundle exec rake test
508
508
  self-signed, and there is no buffering or rate limiting.
509
509
 
510
510
 
511
- The `yamine-apps` fixture fleet (sibling checkout) exercises
511
+ The `test/fixtures/apps/` fixture fleet exercises
512
512
  detection, inference, and boot across Rails variants, Roda, Sinatra,
513
- bare Rack, Jekyll, compound Procfiles, and a monorepo. CI runs the
514
- fixture sweep automatically.
513
+ bare Rack, Jekyll, compound Procfiles, and a monorepo. It ships with
514
+ the repo and runs as part of the unit suite across the Ruby matrix —
515
+ no sibling checkout, no separate CI job.
515
516
 
516
517
  ## License
517
518
 
@@ -4,6 +4,7 @@ require "digest"
4
4
  require "fileutils"
5
5
  require "json"
6
6
  require "open3"
7
+ require "time"
7
8
 
8
9
  module Yamine
9
10
  # Per-worktree databases. Every worktree directory gets its own database
data/lib/yamine/proxy.rb CHANGED
@@ -566,25 +566,51 @@ module Yamine
566
566
  # the other. Deliberately outside the idle bound: an idle websocket
567
567
  # is legitimate traffic (silence is the normal state), and framing
568
568
  # no longer applies once the connection is hijacked.
569
+ #
570
+ # Whichever direction reaches EOF first tears down BOTH ends, and it
571
+ # has to do that with shutdown before close. The sibling copy is
572
+ # parked in a blocking read on the socket being torn down, and a
573
+ # close from another thread does not interrupt that read on linux (it
574
+ # does on macOS) — so close-only left the parked copy alive forever
575
+ # and `t1.join` never returned: one leaked thread per closed upgrade,
576
+ # plus a `handle` that never unwound, in the root daemon. shutdown(2)
577
+ # changes the socket's kernel state instead of dropping the fd, so
578
+ # the parked read comes back with EOF at once — deterministic, and
579
+ # with no timeout added to a path that must stay unbounded.
569
580
  def pipe_both(client, backend)
570
581
  t1 = Thread.new do
571
582
  IO.copy_stream(client, backend)
572
583
  rescue IOError, SystemCallError
573
584
  nil
574
585
  ensure
575
- backend.close rescue nil
586
+ teardown_half(backend)
576
587
  end
577
588
  t2 = Thread.new do
578
589
  IO.copy_stream(backend, client)
579
590
  rescue IOError, SystemCallError
580
591
  nil
581
592
  ensure
582
- client.close rescue nil
593
+ teardown_half(client)
583
594
  end
584
595
  t1.join
585
596
  t2.join
586
597
  end
587
598
 
599
+ # End one end of a hijacked connection: unblock the sibling copy
600
+ # first, then close. Runs from an ensure, so it swallows everything
601
+ # — an exception escaping here would unwind into the acceptor.
602
+ def teardown_half(sock)
603
+ # An SSLSocket (the TLS client's socket) has no #shutdown; its
604
+ # kernel socket is one level down, and that is the fd the parked
605
+ # read is sitting on.
606
+ io = sock.respond_to?(:shutdown) ? sock : sock.to_io
607
+ io.shutdown(Socket::SHUT_RDWR)
608
+ rescue StandardError
609
+ nil
610
+ ensure
611
+ sock.close rescue nil
612
+ end
613
+
588
614
  # DNS-rebinding boundary: the proxy binds loopback, so any website
589
615
  # that tricks a browser into requesting 127.0.0.1 reaches us. A
590
616
  # foreign Host (outside our TLDs) gets a bare 404 that names nothing —
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Yamine
4
- VERSION = "0.21.0"
4
+ VERSION = "0.21.1"
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yamine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.21.0
4
+ version: 0.21.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kaka Ruto