[Spice-devel] [PATCH spice-streaming-agent v2 3/5] Starts/stops the agent based on VT status
Christophe Fergeau
cfergeau at redhat.com
Tue May 22 12:51:24 UTC 2018
On Tue, May 22, 2018 at 07:46:48AM -0400, Frediano Ziglio wrote:
> >
> > On Mon, May 21, 2018 at 11:45:29AM +0100, Frediano Ziglio wrote:
> > > Check if the current display server is active or not and stream only if
> > > active.
> > > This will allow to support multiple display servers running.
> > > When multiple display servers are running only one have the GPU
> > > associated and is writing to the screen.
> > > Stop capturing and release resources when the display server is not
> > > active and vice versa.
> >
> > Is your goal to achieve something similar to
> > https://cgit.freedesktop.org/spice/linux/vd_agent/commit/?id=93003ec27d98cb47b8ea0435179a66c14ff610ce
> > ?
> >
> > Christophe
> >
>
> I basically need to follow the active session on seat0 (the physical one,
> like the physical display).
> Usually GPU is attached to a single session and by the way we don't want
> to stream all possible sessions active but just the one that is active.
Isn't this something that logind provides rather than the apparently X
specific code you are using in this patch? (see loginctl
list-sessions/show-session).
Christophe
>
> > >
> > > Signed-off-by: Frediano Ziglio <fziglio at redhat.com>
> > > ---
> > > src/Makefile.am | 2 ++
> > > src/eventfd.cpp | 38 ++++++++++++++++++++
> > > src/eventfd.hpp | 34 ++++++++++++++++++
> > > src/spice-streaming-agent.cpp | 65 +++++++++++++++++++++++++++++++----
> > > 4 files changed, 132 insertions(+), 7 deletions(-)
> > > create mode 100644 src/eventfd.cpp
> > > create mode 100644 src/eventfd.hpp
> > >
> > > diff --git a/src/Makefile.am b/src/Makefile.am
> > > index 276478f..ffc52b2 100644
> > > --- a/src/Makefile.am
> > > +++ b/src/Makefile.am
> > > @@ -62,4 +62,6 @@ spice_streaming_agent_SOURCES = \
> > > jpeg.hpp \
> > > stream-port.cpp \
> > > stream-port.hpp \
> > > + eventfd.cpp \
> > > + eventfd.hpp \
> > > $(NULL)
> > > diff --git a/src/eventfd.cpp b/src/eventfd.cpp
> > > new file mode 100644
> > > index 0000000..e3c1e72
> > > --- /dev/null
> > > +++ b/src/eventfd.cpp
> > > @@ -0,0 +1,38 @@
> > > +/* Linux event file descriptors
> > > + *
> > > + * \copyright
> > > + * Copyright 2018 Red Hat Inc. All rights reserved.
> > > + */
> > > +#include <config.h>
> > > +#include "eventfd.hpp"
> > > +
> > > +#include <stdexcept>
> > > +#include <sys/eventfd.h>
> > > +
> > > +template<typename T>
> > > +inline void ignore_result(T /* unused result */) {}
> > > +
> > > +namespace spice {
> > > +namespace streaming_agent {
> > > +
> > > +EventFD::EventFD():
> > > + fd(eventfd(0, EFD_CLOEXEC|EFD_NONBLOCK))
> > > +{
> > > + if (fd < 0) {
> > > + throw std::runtime_error("Failed to create eventfd");
> > > + }
> > > +}
> > > +
> > > +void EventFD::signal()
> > > +{
> > > + uint64_t n = 1;
> > > + ignore_result(write(fd, &n, sizeof(n)));
> > > +}
> > > +
> > > +void EventFD::ack()
> > > +{
> > > + uint64_t n;
> > > + ignore_result(read(fd, &n, sizeof(n)));
> > > +}
> > > +
> > > +}} // namespace spice::streaming_agent
> > > diff --git a/src/eventfd.hpp b/src/eventfd.hpp
> > > new file mode 100644
> > > index 0000000..48a175c
> > > --- /dev/null
> > > +++ b/src/eventfd.hpp
> > > @@ -0,0 +1,34 @@
> > > +/* Linux event file descriptors
> > > + *
> > > + * \copyright
> > > + * Copyright 2018 Red Hat Inc. All rights reserved.
> > > + */
> > > +#ifndef SPICE_STREAMING_AGENT_EVENTFD_HPP
> > > +#define SPICE_STREAMING_AGENT_EVENTFD_HPP
> > > +
> > > +#include <unistd.h>
> > > +
> > > +namespace spice {
> > > +namespace streaming_agent {
> > > +
> > > +class EventFD {
> > > +public:
> > > + EventFD();
> > > + ~EventFD() { close(fd); }
> > > + void signal();
> > > + void ack();
> > > + /**
> > > + * Returns underlying file descriptor.
> > > + * Do not close, should just be used for polling.
> > > + */
> > > + int raw_fd() const { return fd; }
> > > +private:
> > > + EventFD(const EventFD&) = delete;
> > > + void operator=(const EventFD&) = delete;
> > > +
> > > + int fd;
> > > +};
> > > +
> > > +}} // namespace spice::streaming_agent
> > > +
> > > +#endif // SPICE_STREAMING_AGENT_EVENTFD_HPP
> > > diff --git a/src/spice-streaming-agent.cpp b/src/spice-streaming-agent.cpp
> > > index 6388bb2..240b9c7 100644
> > > --- a/src/spice-streaming-agent.cpp
> > > +++ b/src/spice-streaming-agent.cpp
> > > @@ -10,6 +10,7 @@
> > > #include "stream-port.hpp"
> > > #include "error.hpp"
> > > #include "xorg-utils.hpp"
> > > +#include "eventfd.hpp"
> > >
> > > #include <spice/stream-device.h>
> > > #include <spice/enums.h>
> > > @@ -36,6 +37,7 @@
> > > #include <thread>
> > > #include <vector>
> > > #include <string>
> > > +#include <atomic>
> > > #include <functional>
> > > #include <X11/Xlib.h>
> > > #include <X11/extensions/Xfixes.h>
> > > @@ -61,12 +63,21 @@ static bool quit_requested = false;
> > > static bool log_binary = false;
> > > static bool log_frames = false;
> > > static std::set<SpiceVideoCodecType> client_codecs;
> > > +static EventFD update_fd;
> > > +static const char vt_property_name[] = "XFree86_has_VT";
> > > +static const char *stream_port_name =
> > > "/dev/virtio-ports/org.spice-space.stream.0";
> > > +static Atom vt_property = None;
> > > +static std::atomic_bool vt_active;
> > >
> > > -static bool have_something_to_read(StreamPort &stream_port, bool blocking)
> > > +static bool have_something_to_read(StreamPort &stream_port, bool blocking,
> > > int &fd)
> > > {
> > > - struct pollfd pollfd = {stream_port.fd, POLLIN, 0};
> > > + struct pollfd pollfds[2] = {
> > > + { stream_port.fd, POLLIN, 0 },
> > > + { update_fd.raw_fd(), POLLIN, 0 },
> > > + };
> > >
> > > - if (poll(&pollfd, 1, blocking ? -1 : 0) < 0) {
> > > + fd = -1;
> > > + if (poll(pollfds, 2, blocking ? -1 : 0) < 0) {
> > > if (errno == EINTR) {
> > > // report nothing to read, next iteration of the enclosing
> > > loop will retry
> > > return false;
> > > @@ -75,7 +86,13 @@ static bool have_something_to_read(StreamPort
> > > &stream_port, bool blocking)
> > > throw IOError("poll failed on the device", errno);
> > > }
> > >
> > > - if (pollfd.revents & POLLIN) {
> > > + if (pollfds[1].revents & POLLIN) {
> > > + fd = update_fd.raw_fd();
> > > + return true;
> > > + }
> > > +
> > > + if (pollfds[0].revents & POLLIN) {
> > > + fd = stream_port.fd;
> > > return true;
> > > }
> > >
> > > @@ -173,8 +190,18 @@ static void read_command_from_device(StreamPort
> > > &stream_port)
> > > static void read_command(StreamPort &stream_port, bool blocking)
> > > {
> > > while (!quit_requested) {
> > > - if (have_something_to_read(stream_port, blocking)) {
> > > - read_command_from_device(stream_port);
> > > + int fd;
> > > + if (have_something_to_read(stream_port, blocking, fd)) {
> > > + if (fd == stream_port.fd) {
> > > + read_command_from_device(stream_port);
> > > + } else if (fd == update_fd.raw_fd()) {
> > > + update_fd.ack();
> > > + bool vt_active =
> > > ::vt_active.load(std::memory_order_relaxed);
> > > + if (!vt_active) {
> > > + throw std::runtime_error("VT disabled");
> > > + }
> > > + continue;
> > > + }
> > > break;
> > > }
> > >
> > > @@ -305,10 +332,22 @@ send_cursor(StreamPort &stream_port, unsigned width,
> > > unsigned height, int hotspo
> > > static void cursor_changes(StreamPort *stream_port, Display *display, int
> > > event_base)
> > > {
> > > unsigned long last_serial = 0;
> > > + Window rootwindow = DefaultRootWindow(display);
> > >
> > > while (1) {
> > > XEvent event;
> > > XNextEvent(display, &event);
> > > +
> > > + if (event.type == PropertyNotify) {
> > > + if (vt_property == None || event.xproperty.atom !=
> > > vt_property)
> > > + continue;
> > > + // update vt property, activate screen read if needed
> > > + vt_active.store(get_win_prop_int(display, rootwindow,
> > > vt_property) != 0, std::memory_order_relaxed);
> > > + std::atomic_thread_fence(std::memory_order_acquire);
> > > + update_fd.signal();
> > > + continue;
> > > + }
> > > +
> > > if (event.type != event_base + 1) {
> > > continue;
> > > }
> > > @@ -416,7 +455,6 @@ do_capture(StreamPort &stream_port, FILE *f_log)
> > >
> > > int main(int argc, char* argv[])
> > > {
> > > - const char *stream_port_name =
> > > "/dev/virtio-ports/org.spice-space.stream.0";
> > > int opt;
> > > const char *log_filename = NULL;
> > > int logmask = LOG_UPTO(LOG_WARNING);
> > > @@ -522,6 +560,19 @@ int main(int argc, char* argv[])
> > > Window rootwindow = DefaultRootWindow(display);
> > > XFixesSelectCursorInput(display, rootwindow,
> > > XFixesDisplayCursorNotifyMask);
> > >
> > > + vt_property = XInternAtom(display, vt_property_name, True);
> > > + if (vt_property == None) {
> > > + syslog(LOG_ERR, "VT property not found\n");
> > > + return EXIT_FAILURE;
> > > + }
> > > + XSelectInput(display, rootwindow, PropertyChangeMask);
> > > +
> > > + vt_active.store(get_win_prop_int(display, rootwindow, vt_property) !=
> > > 0, std::memory_order_relaxed);
> > > + if (!::vt_active.load(std::memory_order_relaxed)) {
> > > + syslog(LOG_ERR, "VT is disabled");
> > > + return EXIT_FAILURE;
> > > + }
> > > +
> > > int ret = EXIT_SUCCESS;
> > >
> > > try {
>
> Frediano
> _______________________________________________
> Spice-devel mailing list
> Spice-devel at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/spice-devel
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: not available
URL: <https://lists.freedesktop.org/archives/spice-devel/attachments/20180522/5f6c15f8/attachment.sig>
More information about the Spice-devel
mailing list