<feed xmlns='http://www.w3.org/2005/Atom'>
<title>ruby.git/thread_win32.c, branch v4.0.3</title>
<subtitle>The Ruby Programming Language</subtitle>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/'/>
<entry>
<title>Set context_stack on main thread</title>
<updated>2025-09-30T13:47:29+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2025-09-29T22:33:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=d8c8623f50af8f5324e1679ff95b1a2071c0c61e'/>
<id>d8c8623f50af8f5324e1679ff95b1a2071c0c61e</id>
<content type='text'>
We allocate the stack of the main thread using malloc, but we never set
malloc_stack to true and context_stack. If we fork, the main thread may
no longer be the main thread anymore so it reports memory being leaked
in RUBY_FREE_AT_EXIT.

This commit allows the main thread to free its own VM stack at shutdown.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We allocate the stack of the main thread using malloc, but we never set
malloc_stack to true and context_stack. If we fork, the main thread may
no longer be the main thread anymore so it reports memory being leaked
in RUBY_FREE_AT_EXIT.

This commit allows the main thread to free its own VM stack at shutdown.
</pre>
</div>
</content>
</entry>
<entry>
<title>Free rb_native_thread memory at fork</title>
<updated>2025-06-12T19:23:50+00:00</updated>
<author>
<name>Peter Zhu</name>
<email>peter@peterzhu.ca</email>
</author>
<published>2025-06-11T20:21:11+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=6e36841dbd5f52b572b690b8a4c3c534fec43ba8'/>
<id>6e36841dbd5f52b572b690b8a4c3c534fec43ba8</id>
<content type='text'>
We never freed any resources of rb_native_thread at fork because it would
cause it to hang. This is because it called rb_native_cond_destroy for
condition variables.  We can't call rb_native_cond_destroy here because
according to the specs of pthread_cond_destroy:

    Attempting to destroy a condition variable upon which other threads
    are currently blocked results in undefined behavior.

Specifically, glibc's pthread_cond_destroy waits on all the other listeners.
Since after forking all the threads are dead, the condition variable's
listeners will never wake up, so it will hang forever.

This commit changes it to only free the memory and none of the condition
variables.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
We never freed any resources of rb_native_thread at fork because it would
cause it to hang. This is because it called rb_native_cond_destroy for
condition variables.  We can't call rb_native_cond_destroy here because
according to the specs of pthread_cond_destroy:

    Attempting to destroy a condition variable upon which other threads
    are currently blocked results in undefined behavior.

Specifically, glibc's pthread_cond_destroy waits on all the other listeners.
Since after forking all the threads are dead, the condition variable's
listeners will never wake up, so it will hang forever.

This commit changes it to only free the memory and none of the condition
variables.
</pre>
</div>
</content>
</entry>
<entry>
<title>`Ractor::Port`</title>
<updated>2025-05-30T19:01:33+00:00</updated>
<author>
<name>Koichi Sasada</name>
<email>ko1@atdot.net</email>
</author>
<published>2025-05-26T18:58:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=ef2bb61018cd9ccb5b61a3d91911e04a773da4a7'/>
<id>ef2bb61018cd9ccb5b61a3d91911e04a773da4a7</id>
<content type='text'>
* Added `Ractor::Port`
  * `Ractor::Port#receive` (support multi-threads)
  * `Rcator::Port#close`
  * `Ractor::Port#closed?`
* Added some methods
  * `Ractor#join`
  * `Ractor#value`
  * `Ractor#monitor`
  * `Ractor#unmonitor`
* Removed some methods
  * `Ractor#take`
  * `Ractor.yield`
* Change the spec
  * `Racotr.select`

You can wait for multiple sequences of messages with `Ractor::Port`.

```ruby
ports = 3.times.map{ Ractor::Port.new }
ports.map.with_index do |port, ri|
  Ractor.new port,ri do |port, ri|
    3.times{|i| port &lt;&lt; "r#{ri}-#{i}"}
  end
end

p ports.each{|port| pp 3.times.map{port.receive}}

```

In this example, we use 3 ports, and 3 Ractors send messages to them respectively.
We can receive a series of messages from each port.

You can use `Ractor#value` to get the last value of a Ractor's block:

```ruby
result = Ractor.new do
  heavy_task()
end.value
```

You can wait for the termination of a Ractor with `Ractor#join` like this:

```ruby
Ractor.new do
  some_task()
end.join
```

`#value` and `#join` are similar to `Thread#value` and `Thread#join`.

To implement `#join`, `Ractor#monitor` (and `Ractor#unmonitor`) is introduced.

This commit changes `Ractor.select()` method.
It now only accepts ports or Ractors, and returns when a port receives a message or a Ractor terminates.

We removes `Ractor.yield` and `Ractor#take` because:
* `Ractor::Port` supports most of similar use cases in a simpler manner.
* Removing them significantly simplifies the code.

We also change the internal thread scheduler code (thread_pthread.c):
* During barrier synchronization, we keep the `ractor_sched` lock to avoid deadlocks.
  This lock is released by `rb_ractor_sched_barrier_end()`
  which is called at the end of operations that require the barrier.
* fix potential deadlock issues by checking interrupts just before setting UBF.

https://bugs.ruby-lang.org/issues/21262
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* Added `Ractor::Port`
  * `Ractor::Port#receive` (support multi-threads)
  * `Rcator::Port#close`
  * `Ractor::Port#closed?`
* Added some methods
  * `Ractor#join`
  * `Ractor#value`
  * `Ractor#monitor`
  * `Ractor#unmonitor`
* Removed some methods
  * `Ractor#take`
  * `Ractor.yield`
* Change the spec
  * `Racotr.select`

You can wait for multiple sequences of messages with `Ractor::Port`.

```ruby
ports = 3.times.map{ Ractor::Port.new }
ports.map.with_index do |port, ri|
  Ractor.new port,ri do |port, ri|
    3.times{|i| port &lt;&lt; "r#{ri}-#{i}"}
  end
end

p ports.each{|port| pp 3.times.map{port.receive}}

```

In this example, we use 3 ports, and 3 Ractors send messages to them respectively.
We can receive a series of messages from each port.

You can use `Ractor#value` to get the last value of a Ractor's block:

```ruby
result = Ractor.new do
  heavy_task()
end.value
```

You can wait for the termination of a Ractor with `Ractor#join` like this:

```ruby
Ractor.new do
  some_task()
end.join
```

`#value` and `#join` are similar to `Thread#value` and `Thread#join`.

To implement `#join`, `Ractor#monitor` (and `Ractor#unmonitor`) is introduced.

This commit changes `Ractor.select()` method.
It now only accepts ports or Ractors, and returns when a port receives a message or a Ractor terminates.

We removes `Ractor.yield` and `Ractor#take` because:
* `Ractor::Port` supports most of similar use cases in a simpler manner.
* Removing them significantly simplifies the code.

We also change the internal thread scheduler code (thread_pthread.c):
* During barrier synchronization, we keep the `ractor_sched` lock to avoid deadlocks.
  This lock is released by `rb_ractor_sched_barrier_end()`
  which is called at the end of operations that require the barrier.
* fix potential deadlock issues by checking interrupts just before setting UBF.

https://bugs.ruby-lang.org/issues/21262
</pre>
</div>
</content>
</entry>
<entry>
<title>Use atomics for system_working global</title>
<updated>2025-05-15T22:18:10+00:00</updated>
<author>
<name>John Hawthorn</name>
<email>john@hawthorn.email</email>
</author>
<published>2025-05-14T05:36:09+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=d67d169aeae8b05f8b06f4829de6d5f14059cfea'/>
<id>d67d169aeae8b05f8b06f4829de6d5f14059cfea</id>
<content type='text'>
Although it almost certainly works in this case, volatile is best not
used for multi-threaded code. Using atomics instead avoids warnings from
TSan.

This also simplifies some logic, as system_working was previously only
ever assigned to 1, so --system_working &lt;= 0 should always return true
(unless it underflowed).
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Although it almost certainly works in this case, volatile is best not
used for multi-threaded code. Using atomics instead avoids warnings from
TSan.

This also simplifies some logic, as system_working was previously only
ever assigned to 1, so --system_working &lt;= 0 should always return true
(unless it underflowed).
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix style [ci skip]</title>
<updated>2025-04-19T13:02:10+00:00</updated>
<author>
<name>Nobuyoshi Nakada</name>
<email>nobu@ruby-lang.org</email>
</author>
<published>2025-04-19T13:02:10+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=c218862d3c664b4afff5acce55d7a6eb13779809'/>
<id>c218862d3c664b4afff5acce55d7a6eb13779809</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>Proof of Concept: Allow to prevent fork from happening in known fork unsafe API</title>
<updated>2024-09-05T09:43:46+00:00</updated>
<author>
<name>Jean Boussier</name>
<email>jean.boussier@gmail.com</email>
</author>
<published>2024-05-29T14:46:04+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=63cbe3f6ac9feb44a2e43b1f853e2ca7e049316c'/>
<id>63cbe3f6ac9feb44a2e43b1f853e2ca7e049316c</id>
<content type='text'>
[Feature #20590]

For better of for worse, fork(2) remain the primary provider of
parallelism in Ruby programs. Even though it's frowned uppon in
many circles, and a lot of literature will simply state that only
async-signal safe APIs are safe to use after `fork()`, in practice
most APIs work well as long as you are careful about not forking
while another thread is holding a pthread mutex.

One of the APIs that is known cause fork safety issues is `getaddrinfo`.
If you fork while another thread is inside `getaddrinfo`, a mutex
may be left locked in the child, with no way to unlock it.

I think we could reduce the impact of these problem by preventing
in for the most notorious and common cases, by locking around
`fork(2)` and known unsafe APIs with a read-write lock.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
[Feature #20590]

For better of for worse, fork(2) remain the primary provider of
parallelism in Ruby programs. Even though it's frowned uppon in
many circles, and a lot of literature will simply state that only
async-signal safe APIs are safe to use after `fork()`, in practice
most APIs work well as long as you are careful about not forking
while another thread is holding a pthread mutex.

One of the APIs that is known cause fork safety issues is `getaddrinfo`.
If you fork while another thread is inside `getaddrinfo`, a mutex
may be left locked in the child, with no way to unlock it.

I think we could reduce the impact of these problem by preventing
in for the most notorious and common cases, by locking around
`fork(2)` and known unsafe APIs with a read-write lock.
</pre>
</div>
</content>
</entry>
<entry>
<title>Fix some warnings</title>
<updated>2024-08-16T05:51:21+00:00</updated>
<author>
<name>Raed Rizqie</name>
<email>raed.rizqie@gmail.com</email>
</author>
<published>2024-08-16T05:51:21+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=018bd07f07e43a5be8ed94cfbcaac3c742b30b0a'/>
<id>018bd07f07e43a5be8ed94cfbcaac3c742b30b0a</id>
<content type='text'>
* Fix unused functions when no `mmap`.

  ```
  shape.c:285:1: warning: unused function 'redblack_insert' [-Wunused-function]
    285 | redblack_insert(redblack_node_t * tree, ID key, rb_shape_t * value)
        | ^~~~~~~~~~~~~~~
  ```

* Fix unknown warning group '-Wmaybe-uninitialized' with clang.

  ```
  thread_win32.c:596:1: warning: unknown warning group '-Wmaybe-uninitialized', ignored [-Wunknown-warning-option]
    596 | COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized)
        | ^
  ```

Co-authored-by: Nobuyoshi Nakada &lt;nobu.nakada@gmail.com&gt;
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
* Fix unused functions when no `mmap`.

  ```
  shape.c:285:1: warning: unused function 'redblack_insert' [-Wunused-function]
    285 | redblack_insert(redblack_node_t * tree, ID key, rb_shape_t * value)
        | ^~~~~~~~~~~~~~~
  ```

* Fix unknown warning group '-Wmaybe-uninitialized' with clang.

  ```
  thread_win32.c:596:1: warning: unknown warning group '-Wmaybe-uninitialized', ignored [-Wunknown-warning-option]
    596 | COMPILER_WARNING_IGNORED(-Wmaybe-uninitialized)
        | ^
  ```

Co-authored-by: Nobuyoshi Nakada &lt;nobu.nakada@gmail.com&gt;
</pre>
</div>
</content>
</entry>
<entry>
<title>`rb_thread_sched_destroy` is not used now at all</title>
<updated>2024-03-22T09:53:44+00:00</updated>
<author>
<name>Nobuyoshi Nakada</name>
<email>nobu@ruby-lang.org</email>
</author>
<published>2024-03-22T09:53:44+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=e2a9b87126d59e4766479a7aa12cf7a648f46506'/>
<id>e2a9b87126d59e4766479a7aa12cf7a648f46506</id>
<content type='text'>
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
</pre>
</div>
</content>
</entry>
<entry>
<title>`rb_thread_lock_native_thread()`</title>
<updated>2024-02-21T06:38:29+00:00</updated>
<author>
<name>Koichi Sasada</name>
<email>ko1@atdot.net</email>
</author>
<published>2024-02-20T10:09:23+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=d578684989fd2d75f086a259719e3eb0fe57ccb2'/>
<id>d578684989fd2d75f086a259719e3eb0fe57ccb2</id>
<content type='text'>
Introduce `rb_thread_lock_native_thread()` to allocate dedicated
native thread to the current Ruby thread for M:N threads.
This C API is similar to Go's `runtime.LockOSThread()`.

Accepted at https://github.com/ruby/dev-meeting-log/blob/master/2023/DevMeeting-2023-08-24.md
(and missed to implement on Ruby 3.3.0)
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Introduce `rb_thread_lock_native_thread()` to allocate dedicated
native thread to the current Ruby thread for M:N threads.
This C API is similar to Go's `runtime.LockOSThread()`.

Accepted at https://github.com/ruby/dev-meeting-log/blob/master/2023/DevMeeting-2023-08-24.md
(and missed to implement on Ruby 3.3.0)
</pre>
</div>
</content>
</entry>
<entry>
<title>Make stack bounds detection work with ASAN</title>
<updated>2024-01-18T22:55:12+00:00</updated>
<author>
<name>KJ Tsanaktsidis</name>
<email>kj@kjtsanaktsidis.id.au</email>
</author>
<published>2023-11-12T02:34:43+00:00</published>
<link rel='alternate' type='text/html' href='https://git.ruby-lang.org/ruby.git/commit/?id=cabdaebc701217049d8a6457c5100f23910f4423'/>
<id>cabdaebc701217049d8a6457c5100f23910f4423</id>
<content type='text'>
Where a local variable is used as part of the stack bounds detection, it
has to actually be on the stack. ASAN can put local variable on "fake
stacks", however, with addresses in different memory mappings. This
completely destroys the stack bounds calculation, and can lead to e.g.
things not getting GC marked on the machine stack or stackoverflow
checks that always fail.

The __asan_addr_is_in_fake_stack helper can be used to get the _real_
stack address of such variables, and thus perform the stack size
calculation properly

[Bug #20001]
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Where a local variable is used as part of the stack bounds detection, it
has to actually be on the stack. ASAN can put local variable on "fake
stacks", however, with addresses in different memory mappings. This
completely destroys the stack bounds calculation, and can lead to e.g.
things not getting GC marked on the machine stack or stackoverflow
checks that always fail.

The __asan_addr_is_in_fake_stack helper can be used to get the _real_
stack address of such variables, and thus perform the stack size
calculation properly

[Bug #20001]
</pre>
</div>
</content>
</entry>
</feed>
