pidfd 1.0.0 → 1.0.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: b451bbd5118d146b771d9163937c333e2b1bb648388844e3a3701020e9ce6c9c
4
- data.tar.gz: c453e8405ab02686a13c1431e2bed5eebba174a4f1abd053c9a0c522727fd280
3
+ metadata.gz: 7c498e89e5d07cb2d256846016a70bf0aece20a8bf145664cf6516637b7b4b84
4
+ data.tar.gz: 45ef88b384618b3d83b9fcc147b582154e01dd05fad36875e529d56cbe964d97
5
5
  SHA512:
6
- metadata.gz: 9ed79dfc7bac514be6b9decbb4ccd6a8e25e4f1f8c917c9d7e8142fb3e7d564c9f530a541a1b762322e40d87eb4b5450c3d8e5d7ec03fe3b79ac7d7a3ce05e08
7
- data.tar.gz: aaacf4562f99d333976ff5227038c0c50972e8bcc82c9f188bb9188760122d146c62c4e7d4c9761eef92a5cc4b36b9d45ba8899be66109f8da21f7fc7264672e
6
+ metadata.gz: e0454d5fe4fefd3a5095a63a79666e1d7ea794ce8b4cfd5b96475c79bab981ddc82a750fb77a26ae8fb04fbf5416ffda053eca8efa64b0fa4d049b5c2cc0f544
7
+ data.tar.gz: 3b034e4305df0eba9ccd3e718a32e6a47632602a1176064f36e9684b626e406922538687065c5f32dc005e7f94f9508038a9a8018b8719bfadb66c6942917e2b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,10 @@
1
1
  # Pidfd Changelog
2
2
 
3
+ ## 1.0.1 (2026-11-02)
4
+ - [Breaking] Drop support for Ruby 3.2 (EOL March 2026). Minimum required Ruby is now 3.3.
5
+ - [Enhancement] Use dynamic Ruby warning category opt-in in test helpers
6
+ - [Change] Document Linux 5.4 as the minimum kernel. `#cleanup` uses `waitid(P_PIDFD)`, which Linux supports since 5.4. The 0.5.0 entry stated 5.3.
7
+
3
8
  ## 1.0.0 (2025-09-05)
4
9
  - [Change] No changes. Just versioning update.
5
10
 
data/README.md CHANGED
@@ -24,7 +24,7 @@ Pidfds provide a **stable reference** to a process that remains valid even if th
24
24
  - **Race-free signal delivery** - Signals always go to the intended process
25
25
  - **Reliable process monitoring** - Know definitively when a process exits
26
26
  - **Thread-safe operations** - No TOCTTOU races
27
- - **Pollable file descriptors** - Integrate with event loops efficiently
27
+ - **Pollable file descriptors** - The kernel marks a pidfd readable when its process exits
28
28
 
29
29
  ## When to Use This Gem
30
30
 
@@ -38,7 +38,7 @@ Use pidfd when you need:
38
38
 
39
39
  Don't use pidfd for:
40
40
  - macOS or Windows (Linux-only feature)
41
- - Kernels older than Linux 5.3
41
+ - Kernels older than Linux 5.4
42
42
  - Simple parent-child relationships (traditional wait works fine)
43
43
 
44
44
  ## Installation
@@ -63,8 +63,8 @@ gem install pidfd
63
63
 
64
64
  ## Requirements
65
65
 
66
- - Linux kernel 5.3 or newer
67
- - Ruby 3.2 or newer
66
+ - Linux kernel 5.4 or newer
67
+ - Ruby 3.3 or newer
68
68
  - FFI gem
69
69
 
70
70
  ## Usage
@@ -115,13 +115,13 @@ pidfd = Pidfd.new(pid)
115
115
  pidfd.signal('TERM') # Guaranteed to hit the right process or fail safely
116
116
  ```
117
117
 
118
- ### Integration with Event Loops
118
+ ### Waiting for a Process to Exit
119
+
120
+ `Pidfd` does not expose its file descriptor, so you cannot pass a `Pidfd` to `IO.select` or an event loop. `alive?` checks the pidfd with a zero timeout, so the check does not wait for the process to exit. To wait for a process to exit, poll `alive?`:
119
121
 
120
122
  ```ruby
121
- # Pidfd provides a pollable file descriptor
122
123
  pidfd = Pidfd.new(child_pid)
123
124
 
124
- # Use with IO.select for non-blocking monitoring
125
125
  loop do
126
126
  if pidfd.alive?
127
127
  # Process still running
@@ -146,6 +146,8 @@ else
146
146
  end
147
147
  ```
148
148
 
149
+ `Pidfd.supported?` tests only `pidfd_open`, so it also returns `true` on Linux 5.3. On 5.3, `#cleanup` does not reap the process, because `waitid(P_PIDFD)` needs Linux 5.4. If your code can run on 5.3, check the kernel version yourself.
150
+
149
151
  ### Fallback Strategy
150
152
 
151
153
  ```ruby
@@ -202,7 +204,7 @@ end
202
204
  - **Efficient**: Pidfd operations are kernel-level, very fast
203
205
  - **Low overhead**: Minimal memory usage per pidfd
204
206
  - **Scalable**: Handles thousands of processes efficiently
205
- - **Non-blocking**: Supports async operation patterns
207
+ - **Non-blocking**: The `alive?` check uses a zero timeout and does not wait for the process to exit
206
208
 
207
209
  ## Security
208
210
 
data/lib/pidfd/errors.rb CHANGED
@@ -2,14 +2,18 @@
2
2
 
3
3
  class Pidfd
4
4
  # Namespace for all the pidfd errors
5
+ # @api public
5
6
  module Errors
6
7
  # Base error class for all pidfd errors
8
+ # @api public
7
9
  BaseError = Class.new(StandardError)
8
10
 
9
11
  # Error raised when pidfd_open syscall fails
12
+ # @api public
10
13
  PidfdOpenFailedError = Class.new(BaseError)
11
14
 
12
15
  # Error raised when pidfd_signal syscall fails
16
+ # @api public
13
17
  PidfdSignalFailedError = Class.new(BaseError)
14
18
  end
15
19
  end
data/lib/pidfd/version.rb CHANGED
@@ -2,5 +2,6 @@
2
2
 
3
3
  class Pidfd
4
4
  # Current version of the pidfd gem
5
- VERSION = '1.0.0'
5
+ # @api public
6
+ VERSION = "1.0.1"
6
7
  end
data/lib/pidfd.rb CHANGED
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'ffi'
3
+ require "ffi"
4
4
 
5
5
  # Main class that wraps Linux pidfd functionality for Ruby
6
+ # @api public
6
7
  class Pidfd
7
8
  extend FFI::Library
8
9
 
@@ -29,29 +30,33 @@ class Pidfd
29
30
  # Wait for child processes that have exited
30
31
  WEXITED = 4
31
32
 
32
- # Default syscall numbers for x86_64 Linux
33
- # These can be overridden if needed for different architectures
34
- # Pidfd open call number
33
+ # Default syscall numbers for x86_64 Linux. These can be overridden if needed for different
34
+ # architectures. Pidfd open call number
35
+ # @api public
35
36
  DEFAULT_PIDFD_OPEN_SYSCALL = 434
36
37
 
37
38
  # Pidfd signal call number
39
+ # @api public
38
40
  DEFAULT_PIDFD_SIGNAL_SYSCALL = 424
39
41
 
40
42
  private_constant :P_PIDFD, :WEXITED
41
43
 
42
44
  class << self
43
45
  # @return [Integer] syscall number for pidfd_open
46
+ # @api public
44
47
  attr_accessor :pidfd_open_syscall
45
48
 
46
49
  # @return [Integer] syscall number for pidfd_signal
50
+ # @api public
47
51
  attr_accessor :pidfd_signal_syscall
48
52
 
49
53
  # @return [Boolean] true if syscall is supported via FFI
54
+ # @api public
50
55
  def supported?
51
56
  # If we were not even able to load the FFI C lib, it won't be supported
52
57
  return false unless API_SUPPORTED
53
58
  # Won't work on macOS because it does not support pidfd
54
- return false if RUBY_DESCRIPTION.include?('darwin')
59
+ return false if RUBY_DESCRIPTION.include?("darwin")
55
60
  # Won't work on Windows for the same reason as on macOS
56
61
  return false if RUBY_DESCRIPTION.match?(/mswin|ming|cygwin/)
57
62
 
@@ -71,6 +76,7 @@ class Pidfd
71
76
  self.pidfd_signal_syscall = DEFAULT_PIDFD_SIGNAL_SYSCALL
72
77
 
73
78
  # @param pid [Integer] pid of the node we want to work with
79
+ # @api public
74
80
  def initialize(pid)
75
81
  @mutex = Mutex.new
76
82
 
@@ -80,6 +86,7 @@ class Pidfd
80
86
  end
81
87
 
82
88
  # @return [Boolean] true if given process is alive, false if no longer
89
+ # @api public
83
90
  def alive?
84
91
  @pidfd_select ||= [@pidfd_io]
85
92
 
@@ -98,6 +105,7 @@ class Pidfd
98
105
 
99
106
  # Cleans the zombie process
100
107
  # @note This should run **only** on processes that exited, otherwise will wait
108
+ # @api public
101
109
  def cleanup
102
110
  @mutex.synchronize do
103
111
  return if @cleaned
@@ -117,6 +125,7 @@ class Pidfd
117
125
  # @return [Boolean] true if signal was sent, otherwise false or error raised. `false`
118
126
  # returned when we attempt to send a signal to a dead process
119
127
  # @note It will not send signals to dead processes
128
+ # @api public
120
129
  def signal(sig_name)
121
130
  @mutex.synchronize do
122
131
  return false if @cleaned
@@ -155,5 +164,5 @@ class Pidfd
155
164
  end
156
165
  end
157
166
 
158
- require_relative 'pidfd/version'
159
- require_relative 'pidfd/errors'
167
+ require_relative "pidfd/version"
168
+ require_relative "pidfd/errors"
data/pidfd.gemspec CHANGED
@@ -1,33 +1,34 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'lib/pidfd/version'
3
+ require_relative "lib/pidfd/version"
4
4
 
5
5
  Gem::Specification.new do |spec|
6
- spec.name = 'pidfd'
6
+ spec.name = "pidfd"
7
7
  spec.version = Pidfd::VERSION
8
- spec.authors = ['Maciej Mensfeld']
9
- spec.email = ['maciej@mensfeld.pl']
8
+ spec.authors = ["Maciej Mensfeld"]
9
+ spec.email = ["maciej@mensfeld.pl"]
10
10
 
11
- spec.summary = 'Ruby wrapper for Linux pidfd system calls'
12
- spec.homepage = 'https://github.com/mensfeld/pidfd'
13
- spec.license = 'MIT'
11
+ spec.summary = "Ruby wrapper for Linux pidfd system calls"
12
+ spec.homepage = "https://github.com/mensfeld/pidfd"
13
+ spec.license = "MIT"
14
14
  spec.description = <<~DESC
15
15
  Provides race-free process management using Linux pidfd (process file descriptors) for safer
16
16
  signal delivery and process monitoring
17
17
  DESC
18
18
 
19
- spec.required_ruby_version = '>= 3.2.0'
19
+ spec.required_ruby_version = ">= 3.3.0"
20
20
 
21
- spec.metadata['homepage_uri'] = spec.homepage
22
- spec.metadata['allowed_push_host'] = 'https://rubygems.org'
23
- spec.metadata['source_code_uri'] = 'https://github.com/mensfeld/pidfd'
24
- spec.metadata['changelog_uri'] = 'https://github.com/mensfeld/pidfd/blob/main/CHANGELOG.md'
25
- spec.metadata['documentation_uri'] = 'https://github.com/mensfeld/pidfd#readme'
26
- spec.metadata['rubygems_mfa_required'] = 'true'
21
+ spec.metadata["homepage_uri"] = spec.homepage
22
+ spec.metadata["allowed_push_host"] = "https://rubygems.org"
23
+ spec.metadata["source_code_uri"] = "https://github.com/mensfeld/pidfd"
24
+ spec.metadata["changelog_uri"] = "https://github.com/mensfeld/pidfd/blob/master/CHANGELOG.md"
25
+ spec.metadata["documentation_uri"] = "https://github.com/mensfeld/pidfd#readme"
26
+ spec.metadata["bug_tracker_uri"] = "https://github.com/mensfeld/pidfd/issues"
27
+ spec.metadata["rubygems_mfa_required"] = "true"
27
28
 
28
29
  # Specify which files should be added to the gem when it is released.
29
- spec.files = Dir.glob('{lib}/**/*') + %w[LICENSE CHANGELOG.md README.md pidfd.gemspec]
30
- spec.require_paths = ['lib']
30
+ spec.files = Dir.glob("{lib}/**/*") + %w[LICENSE CHANGELOG.md README.md pidfd.gemspec]
31
+ spec.require_paths = ["lib"]
31
32
 
32
- spec.add_dependency 'ffi', '>= 1.15'
33
+ spec.add_dependency "ffi", ">= 1.15"
33
34
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pidfd
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0
4
+ version: 1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maciej Mensfeld
@@ -46,8 +46,9 @@ metadata:
46
46
  homepage_uri: https://github.com/mensfeld/pidfd
47
47
  allowed_push_host: https://rubygems.org
48
48
  source_code_uri: https://github.com/mensfeld/pidfd
49
- changelog_uri: https://github.com/mensfeld/pidfd/blob/main/CHANGELOG.md
49
+ changelog_uri: https://github.com/mensfeld/pidfd/blob/master/CHANGELOG.md
50
50
  documentation_uri: https://github.com/mensfeld/pidfd#readme
51
+ bug_tracker_uri: https://github.com/mensfeld/pidfd/issues
51
52
  rubygems_mfa_required: 'true'
52
53
  rdoc_options: []
53
54
  require_paths:
@@ -56,14 +57,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
56
57
  requirements:
57
58
  - - ">="
58
59
  - !ruby/object:Gem::Version
59
- version: 3.2.0
60
+ version: 3.3.0
60
61
  required_rubygems_version: !ruby/object:Gem::Requirement
61
62
  requirements:
62
63
  - - ">="
63
64
  - !ruby/object:Gem::Version
64
65
  version: '0'
65
66
  requirements: []
66
- rubygems_version: 3.6.9
67
+ rubygems_version: 4.0.20
67
68
  specification_version: 4
68
69
  summary: Ruby wrapper for Linux pidfd system calls
69
70
  test_files: []