Changed the check from `bytes` to `err` for safety's sake, too.
This will prevent the potential bug of allocating non-zero memory, then
doing a zeroed resize, which will result in having garbage data in the
initial half.
The backup allocator is set at `init` and must stay the same for the
lifetime of the Scratch allocator, as this allocator is used to free all
`leaked_allocations`. Changing it could lead to a situation where the
wrong allocator is used to free a leaked allocation.
This will cause an error if the memory being resized was not the last
allocation, as should be expected according to the description that this
"acts just like stack_free."
1. The size was being adjusted for the alignment which does not make any
sense without the context of the base pointer. Now we just add the
`alignment - 1` to the size if needed then adjust the pointer.
2. The root pointer of the last allocation is now stored in order to
make the free operation more useful (and to cover the right memory
region for ASan).
3. Resizing now only works on the last allocation instead of any address
in a valid range, which resulted in overwriting allocations that had
just been made.
4. `old_memory` is now re-poisoned entirely before the resized range is
returned with the new range unpoisoned. This will guarantee that
there are no unpoisoned gaps.
Fixes#2694
This fixes an issue where a call to close could intercept the dance
between send and recv, causing send to report incorrectly that a value
was not transmitted (when it actually was).
This test is designed to ensure that a call to send will always
correctly report whether the value was transmitted. If recv wins, a
close call should not be able to intercept the send thread.
This commit makes send behave the same as recv: that the call will
return false if the channel is closed while a thread is waiting on the
blocking operation.
Prior logic would have send return true even if the channel was actually
closed rather than read from.
Docs adjusted to make this clear.
Tests added to lock in this behaviour.
This test ensures that contending threads racing to try_send against a
single blocking read will result in exactly one winner without any
senders blocking.
This changes the semantics of try_send to be consistently non-blocking.
That is, if the buffered is full OR there are no readers it returns
false.
The previous behaviour was such that it would block in the latter case
of no reader, and it would wait for a reader. That is problematic
because it produces inconsistent behaviour between buffered and
unbuffered channels which is astonishing and adds complexity to the
caller.
To illustrate the problem with the old behaviour, consider the
try_select operation: if a send-channel happens to be unbuffered the
try_select (which wants to never block) can now block, that unbuffered
send channel is selected (at random) and there is no reader on the other
side. Thus we have unpredictable blocking behaviour, which breaks the
guarantee that try_select never blocks.
If you want a blocking send you can just call "send" (the blocking
variant).
In addition, there is some reader/writer math done inside
can_{send,recv} such that they only report true if there is sufficient
reader/writer capacity. If there is contention we need to ensure that
each reader is paired to exactly one writer.
Consider try_send: if there is a single reader we can send. If there is
a single reader and a single writer, then we cannot send, as that reader
will be paired with the existing writer. Therefore can_send is only true
if there are more readers than writers at the time of check.
NOTE: The original tests don't need to use wait-looping with thread.yield()
or heuristic sleep. Instead we can just use blocking channel operations
rather than non-blocking operations.
These tests will race access to __global_context_for_test, which can
cause the test suite to flake. Even though only a single test actually
references the variable, the logic in try_select consumes it.
This test harness ensures consistent non-blocking semantics and
validates that we have solved the toctou condition.
The __global_context_for_test is a bit of a hack to fuse together the
test supplied proc and the executing logic in packaage chan.