8000 Fix pure ruby `comm_inactivity_timeout` by nevans · Pull Request #1019 · eventmachine/eventmachine · GitHub
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

Fix pure ruby comm_inactivity_timeout #1019

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

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 12 additions & 27 deletions .github/workflows/workflow.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,16 @@ name: CI
on: [ push, pull_request, workflow_dispatch ]

jobs:
ruby-versions:
uses: ruby/actions/.github/workflows/ruby_versions.yml@master
with:
engine: cruby
# We currently support four EOL versions of ruby, but only on linux
# versions that were released before that version of ruby went EOL.
min_version: 2.5

build:
needs: ruby-versions
name: >-
${{ matrix.os }} ${{ matrix.ruby }}
runs-on: ${{ matrix.os }}
Expand All @@ -21,9 +30,7 @@ jobs:
- macos-14 # arm64
- windows-2022

# We currently support four EOL versions of ruby, but only on linux
# versions that were released before that version of ruby went EOL.
ruby: [ '2.5', '2.6', '2.7', '3.0', '3.1', '3.2', '3.3', head ]
ruby: ${{ fromJson(needs.ruby-versions.outputs.versions) }}

include:
- { os: windows-2022, ruby: ucrt } # used instead of "head"
Expand Down Expand Up @@ -85,30 +92,8 @@ jobs:
CI: true
TESTOPTS: -v --no-show-detail-immediately

pure_ruby:
name: >-
pure ruby (${{ matrix.os }} ${{ matrix.ruby }})
runs-on: ${{ matrix.os }}
timeout-minutes: 10
env:
BUNDLE_WITHOUT: documentation
strategy:
fail-fast: false
matrix:
# TODO: Fix macos-13, macos-14, windows-2022
os: [ ubuntu-20.04, ubuntu-22.04, ubuntu-24.04 ]
ruby: [ '3.1', '3.2', '3.3', head ]
steps:
- name: repo checkout
uses: actions/checkout@v4

- name: Set up Ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: ${{ matrix.ruby }}
bundler-cache: true

- name: test_em_pure_ruby
- name: test pure_ruby
if: startsWith(matrix.os, 'ubuntu')
run: bundle exec rake test_em_pure_ruby
env:
CI: true
Expand Down
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ source 'https://rubygems.org'
gemspec

gem 'rake'
gem 'ostruct'

install_if -> { RUBY_VERSION > '3.1' } do
gem 'net-smtp'
Expand Down
57 changes: 45 additions & 12 deletions lib/em/pure_ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -127,11 +127,11 @@ def initialize_event_machine
Reactor.instance.initialize_for_run
end

# Changed 04Oct06: intervals from the caller are now in milliseconds, but our native-ruby
# processor still wants them in seconds.
# Changed 2025-02-12: intervals from the caller are now in milliseconds, but
# our native-ruby processor still stores them in microseconds.
# @private
def add_oneshot_timer interval
Reactor.instance.install_oneshot_timer(interval.to_f / 1000)
Reactor.instance.install_oneshot_timer(interval * 1000)
end

# @private
Expand Down Expand Up @@ -228,6 +228,10 @@ def send_datagram target, data, datalength, host, port
selectable.send_datagram data, Socket::pack_sockaddr_in(port, host)
end

# @private
def current_time
Reactor.instance.current_time
end

# Sets reactor quantum in milliseconds. The underlying Reactor function wants a (possibly
# fractional) number of seconds.
Expand Down Expand Up @@ -489,10 +493,16 @@ def read_keyboard
EvmaKeyboard.open.uuid
end

# @private
def get_comm_inactivity_timeout sig
s = Reactor.instance.get_selectable( sig ) or raise "unknown get_comm_inactivity_timeout target"
s.get_comm_inactivity_timeout
end

# @private
def set_comm_inactivity_timeout sig, tm
r = Reactor.instance.get_selectable( sig ) or raise "unknown set_comm_inactivity_timeout target"
r.set_inactivity_timeout tm
r.set_comm_inactivity_timeout tm
end

# @private
Expand Down Expand Up @@ -592,6 +602,7 @@ class Reactor
include Singleton

HeartbeatInterval = 2
HeartbeatIntervalMicrosec = HeartbeatInterval * 1_000_000

attr_reader :current_loop_time, :stop_scheduled

Expand All @@ -605,7 +616,7 @@ def get_timer_count

def install_oneshot_timer interval
uuid = UuidGenerator::generate
(@timers_to_add || @timers) << [Time.now + interval, uuid]
(@timers_to_add || @timers) << [get_current_loop_time + interval, uuid]
uuid
end

Expand All @@ -620,8 +631,13 @@ def initialize_for_run
@timers_to_add = SortedSet.new
@timers_iterating = false # only set while iterating @timers
set_timer_quantum(0.1)
@current_loop_time = Time.now
@next_heartbeat = @current_loop_time + HeartbeatInterval
@current_loop_time = get_current_loop_time
@next_heartbeat = @current_loop_time + HeartbeatIntervalMicrosec
end

def current_time
sec, subsec = @current_loop_time.divmod(1_000_000)
Time.at(sec, subsec, :microsecond)
end

def add_selectable io
Expand All @@ -640,7 +656,7 @@ def run
open_loopbreaker

loop {
@current_loop_time = Time.now
@current_loop_time = get_current_loop_time

break if @stop_scheduled
run_timers
Expand Down Expand Up @@ -680,7 +696,7 @@ def run_timers

def run_heartbeats
if @next_heartbeat <= @current_loop_time
@next_heartbeat = @current_loop_time + HeartbeatInterval
@next_heartbeat = @current_loop_time + HeartbeatIntervalMicrosec
@selectables.each {|k,io| io.heartbeat}
end
end
Expand Down Expand Up @@ -749,6 +765,18 @@ def set_timer_quantum interval_in_seconds
@timer_quantum = interval_in_seconds
end

if defined?(Process::CLOCK_MONOTONIC_RAW)
# Uses CLOCK_MONOTONIC_RAW on the platforms that support it
def get_current_loop_time
Process.clock_gettime(Process::CLOCK_MONOTONIC_RAW, :microsecond)
end
else
# Process.clock_gettime emulates CLOCK_MONOTONIC on some platforms
def get_current_loop_time
Process.clock_gettime(Process::CLOCK_MONOTONIC, :microsecond)
end
end

end

end
Expand All @@ -770,7 +798,8 @@ class IO
def_delegator :@eventmachine_selectable, :get_sockname
def_delegator :@eventmachine_selectable, :send_datagram
def_delegator :@eventmachine_selectable, :get_outbound_data_size
def_delegator :@eventmachine_selectable, :set_inactivity_timeout
def_delegator :@eventmachine_selectable, :get_comm_inactivity_timeout
def_delegator :@eventmachine_selectable, :set_comm_inactivity_timeout
def_delegator :@eventmachine_selectable, :heartbeat
def_delegator :@eventmachine_selectable, :io
def_delegator :@eventmachine_selectable, :io=
Expand Down Expand Up @@ -832,8 +861,12 @@ def get_sockname
nil
end

def set_inactivity_timeout tm
@inactivity_timeout = tm
def get_comm_inactivity_timeout
(@inactivity_timeout || 0.0) / 1_000_000 # convert microseconds to seconds
end

def set_comm_inactivity_timeout tm
@inactivity_timeout = tm * 1_000_000 # convert seconds to microseconds
end

def heartbeat
Expand Down
1 change: 0 additions & 1 deletion rakelib/test.rake
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,6 @@ namespace "test" do
def x509_make_csr(cfg, key)
csr = OpenSSL::X509::Request.new
csr.subject = x509_subject(cfg)
csr.version = cfg.fetch("version", 2) # 2 == v3
csr.public_key = key.public_key
csr.sign key, OpenSSL::Digest::SHA256.new
csr
Expand Down
1 change: 0 additions & 1 deletion tests/fixtures/em-localhost.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ subject:
O: EventMachine
OU: Development
CN: localhost
version: 3

ca: eventmachine-ca

Expand Down
1 change: 0 additions & 1 deletion tests/fixtures/eventmachine-ca.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ subject:
OU: Development
CN: EventMachine Testing CA
emailAddress: eventmachine@example.com
version: 3

ttl_hours: 24

Expand Down
2 changes: 0 additions & 2 deletions tests/test_inactivity_timeout.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ class TestInactivityTimeout < Test::Unit::TestCase

if EM.respond_to? :get_comm_inactivity_timeout
def test_default
pend('FIXME: EM.get_comm_inactivity_timeout is broken in pure ruby mode') if pure_ruby_mode?
EM.run {
c = EM.connect("127.0.0.1", 54321)
assert_equal 0.0, c.comm_inactivity_timeout
Expand All @@ -13,7 +12,6 @@ def test_default
end

def test_set_and_get
pend('FIXME: EM.get_comm_inactivity_timeout is broken in pure ruby mode') if pure_ruby_mode?
EM.run {
c = EM.connect("127.0.0.1", 54321)
c.comm_inactivity_timeout = 2.5
Expand Down
4 changes: 0 additions & 4 deletions tests/test_iterator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ def get_time(n = 1)
end

def test_default_concurrency
pend('FIXME: EM.current_time is broken in pure ruby mode') if pure_ruby_mode?
items = {}
list = 1..10
EM.run {
Expand All @@ -31,7 +30,6 @@ def test_default_concurrency
end

def test_default_concurrency_with_a_proc
pend('FIXME: EM.current_time is broken in pure ruby mode') if pure_ruby_mode?
items = {}
list = (1..10).to_a
original_list = list.dup
Expand All @@ -48,7 +46,6 @@ def test_default_concurrency_with_a_proc
end

def test_concurrency_bigger_than_list_size
pend('FIXME: EM.current_time is broken in pure ruby mode') if pure_ruby_mode?
items = {}
list = [1,2,3]
EM.run {
Expand All @@ -64,7 +61,6 @@ def test_concurrency_bigger_than_list_size
end

def test_changing_concurrency_affects_active_iteration
pend('FIXME: EM.current_time is broken in pure ruby mode') if pure_ruby_mode?
items = {}
list = 1..25
seen = 0
Expand Down
15 changes: 15 additions & 0 deletions tests/test_send_file.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ def setup
end

def test_send_file
if windows? && RUBY_VERSION.start_with?("3.4.")
pend('FIXME: this test is broken on Windows with ruby 3.4.1')
end
File.open( @filename, "w" ) {|f|
f << ("A" * 5000)
}
Expand All @@ -58,6 +61,9 @@ def test_send_file

# EM::Connection#send_file_data has a strict upper limit on the filesize it will work with.
def test_send_large_file
if windows? && RUBY_VERSION.start_with?("3.4.")
pend('FIXME: this test is broken on Windows with ruby 3.4.1')
end
File.open( @filename, "w" ) {|f|
f << ("A" * 1000000)
}
Expand Down Expand Up @@ -100,6 +106,9 @@ def post_init
end

def test_stream_file_data
if windows? && RUBY_VERSION.start_with?("3.4.")
pend('FIXME: this test is broken on Windows with ruby 3.4.1')
end
File.open( @filename, "w" ) {|f|
f << ("A" * 1000)
}
Expand All @@ -118,6 +127,9 @@ def test_stream_file_data
end

def test_stream_chunked_file_data
if windows? && RUBY_VERSION.start_with?("3.4.")
pend('FIXME: this test is broken on Windows with ruby 3.4.1')
end
File.open( @filename, "w" ) {|f|
f << ("A" * 1000)
}
Expand Down Expand Up @@ -173,6 +185,9 @@ def test_em_send_file_data_not_implemented
require 'fastfilereaderext'

def test_stream_large_file_data
if windows? && RUBY_VERSION.start_with?("3.4.")
pend('FIXME: this test is broken on Windows with ruby 3.4.1')
end
File.open( @filename, "w" ) {|f|
f << ("A" * 10000)
}
Expand Down
Loading
0