Use cygwait in take_ownership to allow interruption while waiting to
become owner. Return the cygwait return value or a suitable value to
indicate an error.
raw_read now checks the return value and acts accordingly.
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.
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>
- 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.
- 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.
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.
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>
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.
Sharing the OVERLAPPED struct and event object in there between
read and select calls in the fhandler might have been a nice
optimization way back when, but it is a dangerous, not thread-safe
approach. Fix this by creating per-fhandler, per-call OVERLAPPED
structs and event objects on demand.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Get rid of WaitCommEvent and using overlapped_armed to share the
same overlapped operation between read and select. Rather, make
sure to cancel the overlapped IO before leaving any of these functions.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
- Datatypes were incorrect, especially vmin_ and vtime_.
Change them to cc_t, as in user space.
- Error checking had a gap or two. Debug output used the
wrong formatting.
- Don't use ev member for ClearCommError and WaitCommEvent.
Both returned values are different (error value vs. event
code). The values are not used elsewhere so it doesn't make
sense to store them in the object. Therefore, drop ev member.
- Some variable names were not very helpful. Especially using
n as lpNumberOfBytesTransferred from GetOverlappedResult and
then actually printing it as if it makes sense was quite
puzzeling.
- Rework the loop and the definition of minchars so that it
still makes sense when looping.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
- In xterm compatible mode, "ESC 7" and "ESC 8" do not work properly
in the senario:
1) Execute /bin/ls /bin to fill screen.
2) Sned CSI?1049h to alternate screen.
3) Reduce window size.
4) Send CSI?1049l to resume screen.
5) Send "ESC 7" and "ESC 8".
After sending "ESC 8", the cursor goes to incorrect position. This
patch adds a workaround for this issue.
- This patch makes some detailed behaviour of ESC sequences such as
"CSI Ps L" (IL), "CSI Ps M" (DL) and "ESC M" (RI) in xterm mode
match with real xterm.
fhandler_socket_unix::fixup_after_exec incorrectly calls
fhandler_socket_unix::fixup_after_fork with a NULL parent process
handle. Not only that calling DuplicateHandle with a NULL parent
handle fails, but it's utterly wrong trying to duplicate the handles
at all here.
Rather just set some important values to NULL and reopen the shared
memory region. Create a fixup_helper method to call common code from
fixup_after_fork and fixup_after_exec.
Add comments to other invocations of fixup_after_fork with NULL
handle to mark them as correct this way.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
- PTY has a problem that the key input, which is typed during
windows native app is running, disappear when it returns to shell.
(Problem 3 in https://cygwin.com/ml/cygwin/2020-02/msg00007.html)
This is beacuse pty has two input pipes, one is for cygwin apps
and the other one is for native windows apps. The key input during
windows native program is running is sent to the second input pipe
while cygwin shell reads input from the first input pipe.
This patch realize transfering input data between these two pipes.
- PTY code has a problem that tcsh is terminated if the following
command is executed.
true; chcp &
This seems to be caused by invalid pointer access which occurs
when the process exits during the kill() code is execuetd. This
patch avoids the issue by not using kill().
- With this patch, foreground color and background color are allowed
to be set simultaneously by 24 bit color escape sequence such as
ESC[38;2;0;0;255;48;2;128;128;0m in legacy console mode.
Make fhandler_socket_local::dup and fhandler_socket_local::fcntl (a
new method) call fhandler_base::dup and fhandler_base::fcntl if O_PATH
is set.
We're viewing the socket as a disk file here, but there's no need to
implement the actions of fhandler_disk_file::dup and
fhandler_disk_file::fcntl, which do nothing useful in this case beyond
what the fhandler_base methods do. (The extra actions are only useful
when I/O is going to be done on the file.)
If that flag is not set, or if an attempt is made to open a different
type of socket, the errno is now EOPNOTSUPP instead of ENXIO. This is
consistent with POSIX, starting with the 2016 edition. Earlier
editions were silent on this issue.
Opening is done in a (new) fhandler_socket_local::open method by
calling fhandler_base::open_fs.
Also add a corresponding fhandler_socket_local::close method.
Define a new method fhandler_base::fstatvfs_by_handle, extracted from
fhandler_disk_file::fstatvfs, which gets the statvfs information when
a handle is available.
This will be used in future commits for special files that have been
opened with O_PATH.
- After commit 6cc299f0e2, outputs of
cygwin programs which call both printf() and WriteConsole() are
frequently distorted. This patch fixes the issue.
- The cause of the problem reported in
https://www.cygwin.com/ml/cygwin/2020-01/msg00220.html is that the
chars input before dup() cannot be read from the new file descriptor.
This is because the readahead buffer (rabuf) in the console is newly
created by dup(), and does not inherit from the parent. This patch
fixes the issue.
- After commit e1a0775dc0, the problem
reported in https://www.cygwin.com/ml/cygwin/2020-01/msg00093.html
occurs. For Gnu scren and tmux, calling FreeConsole() on pty close
is necessary. However, if FreeConsole() is called, cygwin setup
with '-h' option does not work. Therefore, the commit
e1a0775dc0 delayed closing pty.
This is the cause of the problem above. Now, instead of delaying
pty close, FreeConsole() is not called if the process is non cygwin
processes such as cygwin setup.
- Since calling system __loadlocale() caused execution error,
PTY used its own NLS function. The cause of the error has been
found, the corresponding code has been rewritten using system
function.
- Previously, input and output pipes were switched together between
the traditional pty and the pseudo console. However, for example,
if stdin is redirected to another device, it is better to leave
input pipe traditional pty side even for non-cygwin program. This
patch realizes such behaviour.
- When the I/O pipe is switched to the pseudo console side, the
behaviour of Ctrl-C was unstable. This rarely happens, however,
for example, shell sometimes crashes by Ctrl-C in that situation.
Furthermore, Ctrl-C was ignored if output of non-cygwin program
is redirected to pipe. This patch fixes these issues.
- select() did not work correctly when both read and except are
polled simultaneously for the same fd and the r/w pipe is switched
to pseudo console side. This patch fixes this isseu.
- Pseudo console support introduced by commit
169d65a577 has some bugs which
cause mismatch between state variables and real pseudo console
state regarding console attaching and r/w pipe switching. This
patch fixes this issue by redesigning the state management.
- Support pseudo console in PTY. Pseudo console is a new feature
in Windows 10 1809, which provides console APIs on virtual
terminal. With this patch, native console applications can work
in PTYs such as mintty, ssh, gnu screen or tmux.
So far negative values were denoting files, positive values
denoting directories. We should prefer a less error prone
method. Redefine virtual_ftype_t to contain only positive
values and replace checks for negativ or positive values with
inline functions virt_ftype_isfile() and virt_ftype_isdir().
Drop outdcated comments referring to numerical virtual_ftype_t
values.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
Add a method fifo_client_handler::pipe_state that queries Windows for
the state of a pipe instance. Use this to help terminate the
listen_client thread cleanly.
If the last client handler is useless, delete it instead of declaring
it invalid.
Add a method fhandler_fifo::check_listen_client_thread that checks
whether the thread is running. Use it in raw_read instead of just
testing the handle listen_client_thr.
On exit from the listen_client thread, make sure there's no pending
FSCTL_PIPE_LISTEN request. Otherwise we might get a client connection
after restarting the thread, and we won't have a handle for
communicating with that client.
Remove the retry loop in the case of STATUS_PIPE_LISTENING; that case
shouldn't occur.
Remove the now-unused fc_connecting value from
fifo_client_connect_state.
It's now up to the caller to pass a handle to open_pipe and, if
desired, to call set_handle on return.
This will be useful for a future commit, in which we will open a
client connection without setting an io_handle.
When opening a duplexer, open a client connection to the first client
handler. Previously we gave the duplexer a bogus write handle, which
was just a duplicate of the first client handler's handle. This meant
that we had a pipe server with no clients connected, and all I/O
attempts failed with STATUS_PIPE_LISTENING.
Extend the last fcntl change to duplexers.
Remove a now unused fifo_client_handler constructor, as well as the
long unusued method fifo_client_handler::connect.
Don't create the pipe in duplex mode; the server handle will only be
used for reading.
The blocking mode of the Windows pipe underlying a writer is set to
match that of the writer itself when the latter is opened. Define
fhandler_fifo::fcntl to keep the pipe and the writer in sync if the
blocking mode is changed via fcntl.
Add methods need_fixup_before, init_fixup_before, and
fixup_before_fork_exec to accomplish this. Stopping the thread makes
sure that the client handler lists of the parent and child remain in
sync while the forking/execing is in progress.
Define fhandler:fifo::fixup_after_exec, which sets listen_client_thr
and lct_termination_evt to NULL. This forces the listen_client thread
to restart on the first attempt to read after an exec. Previously the
exec'd process could hang in fhandler_fifo::raw_read.
Remove fifo_client_handler::connect and move its code into
listen_client_thread. That way we can check the return status when a
client handler's connect_evt is signaled. Previously we incorrectly
assumed there was a successful connection.
Also simplify listen_client_thread in the following ways:
- Replace fhandler_fifo::disconnect_and_reconnect by a new
delete_client_handler method. Now we just delete invalid client
handlers rather than trying to re-use them.
- Try to maintain a client handler list that consists of connected
client handlers and exactly one that is listening for a connection.
This allows us to call WaitForMultipleObjects with only two wait
objects.
- Remove 'dummy_evt' from the fifo_client_handler struct; it is no
longer needed.
- On exit from listen_client_thread, delete the "extra" (listening)
client handler. Otherwise there could be a connection that doesn't
get recorded in the client handler list. This could happen when a
file descriptor is being duplicated.
Don't set the write end of the pipe to non-blocking mode if the FIFO
is opened in blocking mode.
In fhandler_fifo::raw_write in blocking mode, wait for the write to
complete rather than returning -1 with EAGAIN.
If the amount to write is large, write in smaller chunks (of size
determined by a new data member max_atomic_write), as in
fhandler_base_overlapped.
For convenience, add two new NTSTATUS codes, STATUS_THREAD_SIGNALED
and STATUS_THREAD_CANCELED, to ntdll.h.
After copyto is called, make the new fhandler's pipe_name point to the
new fhandler's pipe_name_buf, which is a *copy* of the old fhandler's
pipe_name_buf. Previously, get_pipe_name would return the wrong
result after a clone/dup, causing create_pipe_instance and open_pipe
to fail.
Also, stop the listen_client thread when cloning. Otherwise the
thread can keep accepting connections that the cloned fhandler won't
know about.
Do this via a new method fhandler_fifo::stop_listen_client, extracted
from fhandler_fifo::close.
Add data members 'reader', 'writer', and 'duplexer' to the
fhandler_fifo class. Set them in fhandler_fifo::open. ('duplexer'
replaces the previous '_duplexer'.)
This will be useful in later commits.
The word "client" suggests something that holds a handle to the client
side of the pipe (in Windows terminology). But our
fifo_client_handlers hold a handle the server side of the pipe, and
they *connect* to clients.
- Add 24 bit color support using xterm compatibility mode in
Windows 10 1703 or later.
- Add fake 24 bit color support for legacy console, which uses
the nearest color from 16 system colors.
Make fhandler_base::clear_readahead virtual, and implement
fhandler_fifo::clear_readahead. This is called by
dtable::fixup_after_exec; it clears the readahead in each client.
If a FIFO is opened with O_RDWR access, create the pipe with
read/write access, and make the first client have the handle of that
pipe as its I/O handle.
Adjust fhandler_fifo::raw_read to account for the result of trying to
read from that client if there's no data.
fhandler_fifo::clone called fhandler_base::clone on each client
fhandler. But those fhandlers are actually fhandler_fifo objects, so
when fhandler_base::clone calls copyto, it's actually
fhandler_fifo::copyto that gets called. This can lead to mysterious
crashes.
Fix this by simply calling clone (which translates to
fhandler_fifo::clone) on each client fhandler.
Add static functions peek_fifo, thread_fifo, start_thread_fifo, and
fifo_cleanup to select.cc. These are based on the corresponding pipe
functions, the main difference being that peek_fifo loops through the
connected clients to see if any of them have data available for
reading.
Add the fhandler_fifo methods select_read, select_write, and
select_except.
Add accessor methods get_nclients, get_handle, and is_connected that
are needed by peek_fifo.
Add a hit_eof method that tries to detect whether any clients are
connected. Before concluding that there are none, it gives the
listen_client thread time to update the client data.
Introduce a 'fifo_client_handler' structure that can be used by a
reader to communicate with a writer using an instance of the named
pipe. An fhandler_fifo opened for reading creates a thread that does
the following:
- maintains a list of fifo_client_handlers
- listens for_clients trying to connect
- creates new pipe instances as needed so that there's always at
least one available for connecting.
The pipe instances are initially created in blocking mode, but they
are set to be non-blocking after a connection is made.
fhandler_fifo::raw_read now loops through the connected clients and
reads from the first one that has data available.
New fhandler_fifo methods: add_client, listen_client,
listen_client_thread, check_listen_client_thread.
Replace the create_pipe method by create_pipe_instance, which allows
unlimited pipe instances.
New helper functions: create_event, set_pipe_non_blocking.
Make fhandler_fifo a derived class of fhandler_base instead of
fhandler_base_overlapped.
Replace the create_pipe macro, which is based on
fhandler_pipe::create, by new create_pipe and open_pipe methods.
These use NT functions instead of Win32 functions. Replace fifo_name
by get_pipe_name, which returns a pointer to a UNICODE_STRING.
Remove the fnevent macro, which would now be needed only once.
Add a raw_write method, adapted from fhandler_base::raw_write.
Adapt all functions to the changes above.
timerfd_tracker and timerfd_shared classes:
- Just because handles are shared, we don't have to store them in
shared memory. Move share handles into timerfd_tracker class.
- Drop shared instance counter since it's not required anymore.
timerfd_shared only stores the actual timer data.
- Drop timerfd_shared::create, just set clock id.
- Drop timerfd_shared::dtor, it's not required anymore.
- Drop timerfd_tracker::close, just call dtor where required.
- Rename timerfd_tracker::increment_instances to timerfd_tracker::dup.
It's the only reason it exists...
- timerfd_tracker::dtor now checks the non-shared pointers for NULL
before attempting to close them.
- timerfd_tracker::dtor handles decrementing the local instance count
by itself.
- Add a method timerfd_tracker::init_fixup_after_fork_exec to set
non-shared pointers to NULL. Together with the dtor patches it
fixes a problem with close_on_exec timerfd descriptors.
- Fix a bug in handling the thread synchronization event. It's
actually nice to create it before using it...
- Drop using sec_none{_nih} in InitializeObjectAttributes. It's
an unnecessary roundabout route just to get a NULL pointer.
- Slightly rework timechange window handling.
- Add more comments to explain what happens.
fhandler_timerfd:
- Drop cnew macro, it just hides what happens.
- fhandler_timerfd::fixup_after_exec now calls
timerfd_tracker::init_fixup_after_fork_exec first, so a subsequent
call to timerfd_tracker::dtor only works on valid handles.
- fhandler_timerfd::close directly calls timerfd_tracker::dtor now.
- Drop dtor call in fhandler_timerfd destructor.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
The reopen code neglected to pass along the requested open
mode correctly. This may end up reopening the file with
incorrect access mask, or duplicating the wrong pipe handle.
Signed-off-by: Corinna Vinschen <corinna@vinschen.de>