[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 10:44:07 UTC 2018


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

> 
> 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 {
> -- 
> 2.17.0
> 
> _______________________________________________
> 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/c593386e/attachment-0001.sig>


More information about the Spice-devel mailing list