Tcl Source Code

View Ticket
Login
Ticket UUID: 18f4a94d03b075c6295903f1f7b80f7e15b156d6
Title: 8.7 : a blocking memory channel no longer works.
Type: Bug Version: 8.7a5rc0
Submitter: bll Created on: 2021-06-09 19:16:34
Subsystem: - New Builtin Commands Assigned To: pooryorick
Priority: 7 High Severity: Important
Status: Closed Last Modified: 2024-08-19 14:03:41
Resolution: Invalid Closed By: pooryorick
    Closed on: 2024-08-19 14:03:41
Description:
I have some memory channel code that does:

puts $sendchannel some-data  ; # non-blocking
gets $readchannel myvar  ; # blocking, line buffered

This no longer works on macos.  the fileevent on the read handle
is not triggered, and the gets returns an empty string.  

If I put an 'update idletasks' inbetween the puts/gets, it works.

I have not been able to test on Linux as yet.

Edit 1: Changed subject, as this appears to be a problem on both macos and
windows.
User Comments: pooryorick added on 2024-08-19 14:03:41:

That's fine as long as people don't expect it to stay "fixed".


jan.nijtmans added on 2024-08-18 20:24:14:

Setting the "Resolution" field of this ticket to "Invalid" doesn't make this Bug report invalid. @bll, I value this report, I'm glad it's "Fixed".


pooryorick added on 2024-08-18 20:07:06:

Even if example script happens to work now, this report is still invalid. As the documentation states, for non-blocking mode to work correctly, the application must be using the Tcl event loop.


jan.nijtmans added on 2024-08-13 19:26:15:

Fixed - finally - by reverting [9bcec7cd880540c3]


pooryorick added on 2021-06-16 12:13:21:
An attempt to reproduce any sort of bug based on the provided description and
attached "memsock.test" was fruitless.  This ticket can be closed as invalid.

pooryorick added on 2021-06-16 12:11:45:
As was indicated by the original description of resolving the issue using
[update idletasks], what's needed is some event processing between the write to
one channel and the read from the other.  The attached file,
memsock_vwait.test, accomplishes that by entering an event loop at the top
level, scheduling a main coroutine to be run by that event loop, and then
yielding the coroutine at the key moment to allow some event processing.

pooryorick added on 2021-06-16 11:26:29:

Thank you!

No bug has yet been demonstrated, but I'm working now on a new test case. Perhaps it will expose something.

I used to port more things back to 8.6, but got pushback about making unnecessary changes to a patch release. I no longer want to invest my time in the 8.6 series, but instead focus on 8.7 and above. Other people who care more about 8.6 can port fixes if they consider it worth their time.


jan.nijtmans added on 2021-06-16 10:50:28:
> There may indeed be an outstanding issue regarding writing to a nonblocking
> channel and then attempting to immediately read from it, but such an issue can
> be fixed far more gracefully than by making the revert in question.

Fully agreed. So, I suggest to fix this outstanding issue, and then put it in again.

Another remark: If this is a bug, it should have been applied to Tcl 8.6 as well. Why wasn't that done at the time? Then this outstanding issue would have been discovered much earlier.

For now (just before Tcl 8.7a5) I agree with reverting this. But - as soon as it is corrected - it should be re-applied, but then to both 8.6 and 8.7

pooryorick added on 2021-06-16 10:34:03:

Also, no test case was developed for this report, indicating that an expedient resolution was undertaken rather than a correct one.


pooryorick added on 2021-06-16 10:30:32:

The behaviour this report describes is not a bug. The provided test sets an event handler but then never enters the event loop:

fileevent $ch readable [list ::memsock::readhandler $ch $port $handler]

This behaviour is not supported. Ad event handler on a channel can not not be processed until the event loop is entered. The example may have worked in previous versions of Tcl, but only because of the bug described in [67a5eabbd3d19591] and [TCL_FILE_EVENTS cannot drive async I/O alone].

In the attached "memsock.test" example, "sendget" relies on this event handler noted above to ferry data between the sending channel and the receiving channel. This is an error. That handler should not be activated until the event loop is entered.

This "memsock.test" example attached to this report is in essence a restatment of [refchan, coroutine, and postevent from the "watch" proc], and that issue was already fixed. Unfortunately, in response to this new issue, that fix was reverted, effectively unfixing issue [67a5eabbd3d19591], and therefore unfixing the real bug illustreated by "memsock.test". The work that was reverted represents an important change in the direction of correcting some fundamental issues in Tcl's IO subsystem. That work should be reinstated immediately so that it makes it into the 8.7 release.

There may indeed be an outstanding issue regarding writing to a nonblocking channel and then attempting to immediately read from it, but such an issue can be fixed far more gracefully than by making the revert in question.


jan.nijtmans added on 2021-06-15 14:55:10:

Fixed [a785b5bf5e11645d|here]


jan.nijtmans added on 2021-06-15 13:00:25:

Proposed fix [3f466e55c8|here]


jan.nijtmans added on 2021-06-15 12:46:17:

Thanks for the testcase! I did a bisect with the following result:

 12 BAD     2019-04-24 04:52:22 [9bcec7cd880540c3]
 13 GOOD    2019-04-23 06:50:02 [c4804bce46c2b672]

Conclusion: This [Bugfix] introduced the regression.

Assigning to pouryorick for further analysis.


bll added on 2021-06-12 08:46:47:
Attached a non-minimal program that demonstrates the failure.

bll added on 2021-06-11 15:32:09:
Confirmed that this fails on MacOS, Windows and Linux.

Attachments: