If update_my_handlers fails to duplicate one or more handles, just
mark the corresponding handlers as being in an error state.
But if update_my_handlers is unable to open the process of the
previous owner, it's likely that something serious has gone wrong, so
we continue to make that a fatal error.
When a reader takes ownership in fifo_reader_thread, it now goes
directly to the part of the main loop that listens for a connection.
Previously it went back to the beginning of the loop.
Also, if the reader has to delay taking ownership because the previous
owner has not finished updating the shared fifo_client handlers, it
now checks to see if cancel_evt has been set. Previously it might
have had to spin its wheels unnecessarily only to eventually find that
its thread had been canceled.
Add a bool member 'last_read' to the fifo_client_handler structure,
which is set to true on a successful read. This is used by raw_read
as follows.
When raw_read is called, it first locates the writer (if any) for
which last_read is true. raw_read tries to read from that writer and
returns if there is input available. Otherwise, it proceeds to poll
all the writers, as before.
The effect of this is that if a writer writes some data that is only
partially read, the next attempt to read will continue to read from
the same writer. This should reduce the interleaving of output from
different writers.
When a reader opens, it needs to block if there are no writers open
(unless is is opened with O_NONBLOCK). This is easy for the first
reader to test, since it can just wait for a writer to signal that it
is open (via the write_ready event). But when a second reader wants
to open, all writers might have closed.
To check this, use a new '_nwriters' member of struct fifo_shmem_t,
which keeps track of the number of open writers. This should be more
reliable than the previous method.
Add nwriters_lock to control access to shmem->_nwriters, and remove
reader_opening_lock, which is no longer needed.
Previously only readers had access to the shared memory, but now
writers access it too so that they can increment _nwriters during
open/dup/fork/exec and decrement it during close.
Add an optional 'only_open' argument to create_shmem for use by
writers, which only open the shared memory rather than first trying to
create it. Since writers don't need to access the shared memory until
they have successfully connected to a pipe instance, they can safely
assume that a reader has already created the shared memory.
For debugging purposes, change create_shmem to return 1 instead of 0
when a reader successfully opens the shared memory after finding that
it had already been created.
Remove check_write_ready_evt, write_ready_ok_evt, and
check_write_ready(), which are no longer needed.
When opening a writer and looping to try to get a connection, recheck
read_ready at the top of the loop since the number of readers might
have changed.
To slightly speed up the process of opening the first reader, take
ownership immediately rather than waiting for the fifo_reader_thread
to handle it.
When the owning reader closes and there are still readers open, the
owner needs to wait for a new owner to be found before closing its
fifo_client handlers. This involves a loop in which dec_nreaders is
called at the beginning and inc_nreaders is called at the end. Any
other reader that tries to access shmem->_nreaders during this loop
will therefore get an inaccurate answer.
Fix this by adding an nreaders method and using it instead of
dec_nreaders and inc_nreaders. Also add nreaders_lock to control
access to the shmem->_nreaders.
Make various other changes to improve the reliability of finding a new
owner.
Since FD_CONNECT is only given once, we manually need to set
FD_WRITE for connection failed sockets to have consistent
behaviour in programs calling poll/select multiple times.
Example test to non-listening port: curl -v 127.0.0.1:47
If the acl_t struct was at or above 0x80000000 then the pointer was
sign-extended to 0xffff_ffff_8000_0000 and so the index was lost.
Signed-off-by: David Allsopp <david.allsopp@metastack.com>
This should slightly speed up especially path conversions,
given there's one less function call rearranging all function
arguments in registers/stack (and less stack pressure).
For clarity, rename overloaded sys_wcstombs to _sys_wcstombs
and sys_cp_mbstowcs to _sys_mbstowcs.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Re: CPU microcode reported wrong in /proc/cpuinfo
https://sourceware.org/pipermail/cygwin/2020-May/245063.html
earlier Windows releases used different registry values to store microcode
revisions depending on the MSR name being used to get microcode revisions:
add these alternative registry values to the cpuinfo registry value lookup;
iterate thru the registry data until a valid microcode revision is found;
some revision values are in the high bits, so if the low bits are all clear,
shift the revision value down into the low bits
sys_mbstowcs is called with the destination buffer length
set to MaximumLength from the receiving UNICODE_STRING buffer.
This is twice as much as the actual size of the buffer in
wchar_t units, which is the unit expected by sys_mbstowcs.
sys_mbstowcs always attaches a NUL, within the destination
buffersize given. But if the string is exactly one wchar_t
less than the actual buffer, and the buffersize is given too
large, sys_mbstowcs writes a NUL one wchar_t beyond the buffer.
This has only been exposed with Cygwin 3.1.5 because alloca
on newer gcc 9 apparently allocates more tightly. The alloca
buffer here is requested with 16 bytes, which is exactly the
number of bytes required for the string L"cmd.exe". Older gcc
apparently allocated a few more bytes on the stack, while gcc 9
allocates in 16 byte granularity...
Fix this by giving the correct destination buffer size to
sys_mbstowcs.
Fixes: https://cygwin.com/pipermail/cygwin/2020-June/245226.html
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Use WSAIoctl(SIO_KEEPALIVE_VALS) on older systems.
Make sure that keep-alive timeout is equivalent to
TCP_KEEPIDLE + TCP_KEEPCNT * TCP_KEEPINTVL on older systems,
even with TCP_KEEPCNT being a fixed value on those systems.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
- Drop definitions from <cygwin/sockets.h>
- Drop options only available on BSD
- Fix value of TCP_MAXSEG. It was still defined as the BSD value
while WinSock uses another value
- Handle the fact that TCP_MAXSEG is a R/O value in WinSock
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
- Return value of eat_readahead() is redefined. The return values
of fhandler_termios::eat_readahead() and fhandler_pty_slave::
eat_readahead() were little bit different. This patch unifies
them to number of bytes eaten by eat_readahead().
- Considerration for raixget() is added to fhandler_pty_master::
accept_input() code.
- Transfering contents of read ahead buffer in
fhandler_pty_master::transfer_input_to_pcon() is removed since
it is not necessary.
- fhandler_pty_slave::eat_readahead() ckecks EOL only when ICANON
is set.
- Guard for _POSIX_VDISABLE is added in checking EOL.
- If vim is started from WSL (Ubuntu) which is executed in pseudo
console in mintty, shift key and ctrl key do not work. Though
this issue is similar to the issue resolved by commit
4527541ec6, that commit is not
effective for this issue. This patch fixes the issue by discarding
"CSI > Pm m" in fhandler_pty_master::pty_master_fwd_thread().
- Commit c4b060e3fe seems to be not
enough. Moreover, it does not work as expected at all in Win10
1809. This patch essentially reverts that commit and add another
fix. After all, the cause of the problem was a race issue in
switch_to_pcon_out flag. That is, this flag is set when native
app starts, however, it is delayed by wait_pcon_fwd(). Since the
flag is not set yet when less starts, the data which should go
into the output_handle accidentally goes into output_handle_cyg.
This patch fixes the problem more essentially for the cause of
the problem than previous one.
- If the output of non-cygwin apps is browsed using less, screen is
ocasionally distorted after less exits. This frequently happens
if cmd.exe is executed after less. This patch fixes the issue.
- In current pty, the window title can not be set from non-cygwin
program due to the code which prevents overwriting the window
title to "cygwin-console-helper.exe" in fhandler_pty_master::pty_
master_fwd_thread(). This patch fixes the issue.
- If the cygwin vim is started from a non-cygwin process which is
executed in pseudo console, shift key and ctrl key do not work.
In this case, vim is executed under /dev/cons*. If vim outputs
escape sequence which is not supported by pseudo console, the
escape sequence is leaked into the parent pty. This causes
unexpected results. This patch fixes the issue by discarding
"CSI > Pm m". "OSC 10;? BEL/ST" and "OSC 11;? BEL/ST" are
discarded as well.
- After commit 29431fcb5b, the issue
reported in https://cygwin.com/pipermail/cygwin/2020-May/245057.html
occurs. This is caused by the following mechanism. Cygwin less
called from non-cygwin git is executed under /dev/cons* rather
than /dev/pty* because parent git process only inherits pseudo
console handle. Therefore, less sets ICANON flag for /dev/cons*
rather than original /dev/pty*. When pty is switched to non-cygwin
git process, line_edit() is used in fhandler_pty_master::write()
only to set input_available_event and read ahead buffer is supposed
to be flushed in accept_input(). However, ICANON flag is not set
for /dev/pty*, so accept_input() is not called unless newline
is entered. As a result, the input data remains in the read ahead
buffer. This patch fixes the issue.
Disable -std option since gnu++14 is default anyway, but keep
it available as comment.
Update dynamic exception specifications deprecated with
C++11 to C++11-introduced noexcept expression.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This partially reverts commit
f36262d56a. That commit incorrectly
made the st_mode of a fifo reflect the Windows permissions of the disk
file underlying the fifo.
Rename localtime.c.patched to localtime.patched.c to keep the correct
language suffix.
Create localtime.patched.c in the build dir rather than in the source
dir. Decouple the build rule for creating localtime.patched.c from
the rule to build localtime.o, so we don't have to rebuild the patched
source file all the time.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
That also requires a small tweak to localtime.c.patch, otherwise
GCC complains about the position of the 'trydefrules' label.
Also, simplify includes.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Add tz_posixrules.h with data generated from most recent Cygwin tzdata
package. Establish localtime.cc as primarily a wrapper around a patched
copy of localtime.c. See README for more information.
Modifies winsup/cygwin/Makefile.in to build localtime.o from items in
new winsup/cygwin/tzcode subdirectory. Compiler option "-fpermissive"
is used to accept warnings about missing casts on the return values of
malloc() calls. This patch also removes existing localtime.cc and
tz_posixrules.h from winsup/cygwin as they are superseded by the
subsequent patches in this set.
Both functions are declared as extern "C" functions in
sys/smallprint.h, but as C++ funcs in winsup.h and in the
source itself.
Add extern "C to definitions, remove declarations in winsup.h
and include sys/smallprint.h instead.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
- The number of slaves attached to pseudo console is used only for
triggering redraw screen. Counting was not only needless, but also
did not work as expected. This patch removes the code for counting.
This reverts commit 39a9cd9465.
There is no need to explicitly take ownership in fixup_after_exec; if
ownership transfer is needed, it will be taken care of by
fhandler_fifo::close when the parent closes. Moreover, closing the
parent's fifo_reader_thread can cause problems, such as the one
reported here:
https://cygwin.com/pipermail/cygwin-patches/2020q2/010235.html
- After commit 071b8e0cbd, the problem
reported in https://cygwin.com/pipermail/cygwin/2020-May/244873.html
occurs. This is due to freeing console device accidentally rather
than pseudo console. This patch makes sure to call FreeConsole()
only if the process is attached to the pseudo console of the current
pty.
Windows Explorer shows a warning with Cygwin-created DACLs, but putting
the text of the warning into Google doesn't lead to the relevant Cygwin
docs. Let's copy the warning text into the docs in the hopes of helping
confused users. Most of the credit for the wording belongs to Yaakov
Selkowitz.
Latest inquiry: <https://cygwin.com/pipermail/cygwin/2020-May/244814.html>
Signed-off-by: David Macek <david.macek.0@gmail.com>
During a blocking read, we sleep for 1 ms after each iteration through
the connected writers. Currently we do this by calling Sleep (1).
Remove this call to Sleep and instead change the timeout in the
cygwait call from 0 to 1, so that raw_read can be interrupted while
sleeping.
There are currently three functions that call NtQueryInformationFile
to determine the state of a pipe instance. Do this only once, in a
new fifo_client_handler::set_state () function, and call that when
state information is needed.
Remove the fifo_client_handler methods pipe_state and get_state, which
are no longer needed.
Make fhandler_fifo::get_fc_handler return a reference, for use in
select.cc:peek_fifo.
Make other small changes to ensure that this commit doesn't change any
decisions based on the state of a fifo_client_handler.
The tricky part is interpreting FILE_PIPE_CLOSING_STATE, which we
translate to fc_closing. Our current interpretation, which is not
changing as a result of this commit, is that the writer at the other
end of the pipe instance is viewed as still connected from the point
of view of raw_read and determining EOF.
But it is not viewed as still connected if we are deciding whether to
unblock a new reader that is trying to open.
fifo_reader_id_t::operator == and != have been defined without type
accidentally. For some weird reason, only x86 gcc complains about
this problem, not x86_64 gcc.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
The beginning of fhandler_fifo.cc contains a long comment giving an
overview of the FIFO implementation. This is now updated to describe
the support for multiple readers.
Although we can have multiple readers open because of dup/fork/exec,
the current code does not support multiple readers opening a FIFO by
explicitly calling 'open'.
The main complication in supporting this is that when a blocking
reader tries to open and there's already one open, it has to check
whether there any writers open. It can't rely on the write_ready
event, whose state hasn't changed since the first writer opened.
To fix this, add two new named events, check_write_ready_evt and
write_ready_ok_evt, and a new method, check_write_ready().
The first event signals the owner's reader thread to call
check_write_ready(), which polls the fc_handler list to check for
connected writers. If it finds none, it checks to see if there's a
writer in the process and then sets/resets write_ready appropriately.
When check_write_ready() finishes it sets write_ready_ok_evt to signal
the reader that write_ready has been updated.
The polling is done via fifo_client_handler::pipe_state(). As long as
it's calling that function anyway, check_write_ready() updates the
state of each handler.
Also add a new lock to prevent a race if two readers are trying to
open simultaneously.
Add a take_ownership method, used by raw_read and select.cc:peek_fifo.
It wakes up all fifo_reader_threads and allows the caller to become
owner. The work is done by the fifo_reader_threads.
For synchronization we introduce several new fhandler_fifo data
members and methods:
- update_needed_evt signals the current owner to stop listening for
writer connections and update its fc_handler list.
- shared_fc_handler() gets and sets the status of the fc_handler
update process.
- get_pending_owner() and set_pending_owner() get and set the reader
that is requesting ownership.
Finally, a new 'reading_lock' prevents two readers from trying to take
ownership simultaneously.
If the owning reader is closing, wait for another reader (if there is
one) to take ownership before closing the owner's pipe handles.
To synchronize the ownership transfer, add events owner_needed_evt and
owner_found_evt, and add methods owner_needed and owner_found to
set/reset them.
Modify the fifo_reader_thread function to wake up all non-owners when
a new owner is needed.
Make a cosmetic change in close so that fhandler_base::close is called
only if we have a write handle. This prevents strace output from
being littered with statements that the null handle is being closed.
If fixup_after_exec is called on a non-close-on-exec reader whose
parent is the owner, transfer ownership to the child. Otherwise the
parent's pipe handles will be closed before any other reader can
duplicate them.
To help with this, make the cancel_evt and thr_sync_evt handles
inheritable, so that the child can terminate the parent's
fifo_reader_thread (and the parent will update the shared fc_handler
list).
Add an optional argument 'from_exec' to update_my_handlers to simplify
its use in this case; no handle duplication is required.
This is in a new shared memory section. We will use it for temporary
storage of the owner's fc_handler list when we need to change owner.
The new owner can then duplicate the pipe handles from that list
before taking ownership.
Add several shared data members and methods that are needed for the
duplication process
Add methods update_my_handlers and update_shared_handlers that carry
out the duplication.
Allow the shared list to grow dynamically, up to a point. Do this by
initially reserving a block of memory (currently 100 pages) and only
committing pages as needed.
Add methods create_shared_fc_handler, reopen_shared_fc_handler, and
remap_shared_fc_handler to create the new shared memory section,
reopen it, and commit new pages. The first is called in open, the
second is called in dup/fork/exec, and the third is called in
update_shared_handlers if more shared memory is needed.
Modify the fifo_reader_thread function to call update_my_handlers when
it finds that there is no owner. Also make it call
update_shared_handlers when the owner's thread terminates, so that the
new owner will have an accurate shared fc_handler list from which to
duplicate.
For convenience, add new methods cleanup_handlers and
close_all_handlers. And add an optional arg to add_client_handler
that allows it to create a new fifo_client_handler without creating a
new pipe instance.
Make fc_handler a pointer to malloc'd memory instead of a fixed-size
array. The size is now a new data member 'shandlers'. Call realloc
in add_client_handler if we need to grow the array.
free fc_handler in close. As long as we're touching that code, also
remove an unneeded lock.
Among all the open readers of a FIFO, one is declared to be the owner.
This is the only reader that listens for client connections, and it is
the only one that has an accurate fc_handler list.
Add shared data and methods for getting and setting the owner, as well
as a lock to prevent more than one reader from accessing these data
simultaneously.
Modify the fifo_reader_thread so that it checks the owner at the
beginning of its loop. If there is no owner, it takes ownership. If
there is an owner but it is a different reader, the thread just waits
to be canceled. Otherwise, it listens for client connections as
before.
Remove the 'first' argument from create_pipe_instance. It is not
needed, and it may be confusing in the future since only the owner
knows whether a pipe instance is the first.
When opening a reader, don't return until the fifo_reader_thread has
time to set an owner.
If the owner closes, indicate that there is no longer an owner.
Clear the child's fc_handler list in dup, and don't bother duplicating
the handles. The child never starts out as owner, so it can't use
those handles.
Do the same thing in fixup_after_fork in the close-on-exec case. In
the non-close-on-exec case, the child inherits an fc_handler list that
it can't use, but we can just leave it alone; the handles will be
closed when the child is closed.
This uniquely identifies an fhandler_fifo open for reading in any
process.
Add a new data member 'me' of this type, which is set in open, dup,
fork, and exec.
Add data and methods to the shared memory that keep track of the
number of open readers.
Increment this number in open, dup, fork, and exec. Decrement it in
close. Reset read_ready if there are no readers left.
Even though we currently allow a FIFO to be opened for reading only
once, we can still have more than one reader open because of dup and
fork. Add a named shared memory section accessible to all readers of
a given FIFO. In future commits we will add information needed by all
readers to this section
Add a class fifo_shmem_t that lets us access this information.
Add a method create_shmem that is called when a reader opens, and add
a method reopen_shmem that is called by dup, fork, and exec. (Each
new reader needs its own view of the shared memory.)
This will simplify future work.
Rename the thread from "listen_client_thread" to "fifo_reader_thread"
because it will be used for more than just listening.
Remove the fixup_before stuff, which won't be needed after future
changes to fixup_after_fork and fixup_after_exec.
- Make read_ready a manual-reset event.
- Signal read_ready in open instead of in the listen_client_thread.
- Don't reset read_ready when the listen_client thread terminates;
instead do it in close().
- Rearrange open and change its error handling.
- Add a wait_open_pipe method that waits for a pipe instance to be
available and then calls open_pipe. Use it when opening a writer if
we can't connect immediately. This can happen if the system is
heavily loaded and/or if many writers are trying to open
simultaneously.
According to Posix, a FIFO open for reading is at EOF if it is empty
and there are no writers open.
The only way to test this is to poll the fifo_client_handlers as in
raw_read and select.cc:peek_fifo. The current hit_eof instead relies
on the value of nconnected, which can be out of date. On the one
hand, it doesn't take into account writers that were connected but
have since closed. On the other hand, it doesn't take into account
writers that are in the process of opening but haven't yet connected.
Fix this by introducing a maybe_eof method that tentatively assumes
EOF if there are no connected writers after polling. Then check for
writers currently opening (via a new 'writer_opening' event), and wait
for the fifo_reader_thread to record any new connection that was made
while we were polling.
To handle the needs of peek_fifo, replace the get_fc_handle method
by a get_fc_handler method, and add a fifo_client_handler::get_state
method.
Remove the is_connected method, which was used only in peek_fifo and
is no longer needed.
Remove the nconnected data member, which was used only for the flawed
hit_eof.
Add some comments about events to fhandler.h.
Always return 0; no one is doing anything with the return value
anyway.
Remove the return value from stop_listen_client.
Make the connection event auto-reset, so that we don't have to reset
it later.
Simplify the process of connecting a bogus client when thread
termination is signaled.
Make some failures fatal.
Remove the unnecessary extra check for thread termination near the end
of listen_client_thread.
Make the values correspond to the possible return values of
fifo_client_handler::pipe_state().
When cleaning up the fc_handler list in listen_client_thread(), don't
delete handlers in the fc_closing state. I think the pipe might still
have input to be read in that case.
Set the state to fc_closing later in the same function if a connection
is made and the status returned by NtFsControlFile is
STATUS_PIPE_CLOSING.
In raw_read, don't error out if NtReadFile returns an unexpected
status; just set the state of that handler to fc_error. One writer in
a bad state doesn't justify giving up on reading.
Replace the 'fhandler_base *' member by a HANDLE to the server side of
the Windows named pipe instance. Make the corresponding
simplifications throughout.
When `cygwin-console-helper.exe` is either missing, or corresponds to a
different Cygwin runtime, we currently wait forever while setting up
access to the pseudo console, even long after the process is gone that
was supposed to signal that it set up access to the pseudo console.
Let's handle that more gracefully: if the process exited without
signaling, we cannot use the pseudo console. In that case, let's just
fall back to not using it.
Signed-off-by: Johannes Schindelin <johannes.schindelin@gmx.de>