Page MenuHomePhabricator

Address higher-impact `arc` toolsets behaviors
Open, NormalPublic

Description

arc unit and arc lint no longer prompt you before continuing if there are failures.

In Mercurial, with certain character sets, some arc workflows may fail in arc-hg while trying to perform UTF8 operations.

Shell completion can be trivially simplified.

arc unit and arc lint should have more sensible ordering and summarization of results.

arc alias can't alias diff, etc.

arc alias doesn't list aliases, etc.

arc may leave stdout/stderr nonblocking.

arc no longer automatically provides "Depends on".

Event Timeline

epriestley triaged this task as Normal priority.Apr 6 2021, 3:54 PM
epriestley created this task.

arc may leave stdout/stderr nonblocking.

Ideally, I'd like arc to leave stdout in the state it started in. However, I can't figure out how to actually test if a stream is nonblocking in PHP.

The report in PHI1845 uses Python to invoke fcntl, but literally invoking Python seems a bit beyond the pale.

PHP has dio_fcntl() but this isn't a standard extension. socket_get_option() doesn't seem to be able to read O_NONBLOCK (and this isn't a socket anyway, although PHP is a bit fast-and-loose about this).

stream_get_meta_data() returns a blocked key, which is almost useful, but if that's false we can't distinguish between "nonblocking" and "blocking, but input is available".

I'm just going to assume stdin starts as blocking, since it seems like a reasonable assumption.

I'm also going to assume this method isn't reentrant. Today, there's exactly one callsite that can mess with blocking behavior and it's never-reentrant. If more of this crops up or the method becomes reentrant, this would need some kind of smarter scope guard or stack management to count how many layers of nonblockingness have been applied to the socket.

Actually, blocked is documented as:

blocked (bool) - true if the stream is in blocking IO mode.
https://www.php.net/manual/en/function.stream-get-meta-data

This appears to be the actual behavior of the key:

test.php
<?php

$stdin = fopen('php://stdin', 'r');
var_dump(stream_get_meta_data($stdin));
$ echo abcd | php -f test.php
array(9) {
  ["timed_out"]=>
  bool(false)
  ["blocked"]=>
  bool(true)
...
}

Here, blocked should be false if it really means "blocked" (a read won't block, since I piped text) but it's true, agreeing with the documentation, and the source looks like it literally just reads O_NONBLOCK:

plain_wrapper.c
add_assoc_bool((zval*)ptrparam, "timed_out", 0);
add_assoc_bool((zval*)ptrparam, "blocked", (flags & O_NONBLOCK)? 0 : 1);
add_assoc_bool((zval*)ptrparam, "eof", stream->eof);

So that's good.

I also can't get O_NONBLOCK to survive process exit on macOS. This is possibly because macOS is now zsh, and this RedHat bug suggests that zsh clears O_NONBLOCK:

https://bugzilla.redhat.com/show_bug.cgi?id=1068697

I can't get bash to hold O_NONBLOCK on macOS either, though (on "3.2.57(1)-release" which has a 2007 date), so the exact reproduction environment isn't entirely clear to me.

...this would need some kind of smarter scope guard...

If pcntl is not installed, the user can ^C and dodge a finally block, so this does need to be a guard in all cases.