[Spice-devel] [PATCH 08/14] Use RAII to cleanup stream in case of exception or return

Frediano Ziglio fziglio at redhat.com
Thu Feb 15 14:35:02 UTC 2018


> 
> > On 15 Feb 2018, at 11:04, Frediano Ziglio <fziglio at redhat.com> wrote:
> > 
> >> 
> >> From: Christophe de Dinechin <dinechin at redhat.com>
> >> 
> >> This lets us get rid of C-style 'goto done' in do_capture.
> >> 
> >> Signed-off-by: Christophe de Dinechin <dinechin at redhat.com>
> > 
> > I honestly prefer the "defer" style way.
> 
> The standard C++ practice for resource management is RAII, not defer. RAII is
> a composable abstraction, i.e. I can pile structs in structs and it still
> works.
> 

RAII is supposed to encapsulate a resource, your patch is encapsulating
the allocation and disposal of an external resource, exactly as the defer
generated code/data are doing.
The difference is that your code handle only FILE* while defer supports
different cases.
In a perfect world everything would be already encapsulated in RAII
objects but dealing with C objects the defer style provides much more
reuse.

> I don’t know how you can prefer ‘defer’. It is, in all honestly, a clever but
> vile and ugly hack. Frankly, a C macro? With a lambda? Using a variable
> named after the __LINE__ in the code? It’s not reusable, it stays very low
> level, it’s brittle, hard to write (forget the ; and die). Smart people like
> Uri had to ask on IRC how it worked and what it was supposed to do…
> 

I don't agree with the reuse.
The __LINE__ is to avoid duplications, you could pass a unique name if you prefer.

> > 
> > Beside that you correctly pointed out that there's a race condition
> > on cursor thread which could lead the cursor thread to attempt writing
> > the cursor shape before the device is open and you proposed some fixes
> > in a different series.
> > I think would be a better fix for this.
> 
> But it follows this patch and requires it.
> 

Then propose a correct series. Has been pending for more or less 3 months,
we can't wait ages for a perfect solution and between this patch and the
defer one I prefer the last.

> > 
> >> ---
> >> src/spice-streaming-agent.cpp | 32 ++++++++++++++++++++------------
> >> 1 file changed, 20 insertions(+), 12 deletions(-)
> >> 
> >> diff --git a/src/spice-streaming-agent.cpp b/src/spice-streaming-agent.cpp
> >> index 25a38a6..e9ef310 100644
> >> --- a/src/spice-streaming-agent.cpp
> >> +++ b/src/spice-streaming-agent.cpp
> >> @@ -53,6 +53,23 @@ struct SpiceStreamDataMessage
> >>     StreamMsgData msg;
> >> };
> >> 
> >> +struct Stream
> >> +{
> >> +    Stream(const char *name, int &fd): fd(fd)
> >> +    {
> >> +        fd = open(name, O_RDWR);
> >> +        if (fd < 0)
> >> +            throw std::runtime_error("failed to open streaming device");
> >> +    }
> >> +    ~Stream()
> >> +    {
> >> +        if (fd >= 0)
> >> +            close(fd);
> >> +        fd = -1;
> >> +    }
> >> +    int &fd;
> >> +};
> >> +
> >> static bool streaming_requested = false;
> >> static bool quit_requested = false;
> >> static bool log_binary = false;
> >> @@ -354,17 +371,14 @@ static void cursor_changes(Display *display, int
> >> event_base)
> >> static void
> >> do_capture(const char *streamport, FILE *f_log)
> >> {
> >> -    streamfd = open(streamport.c_str(), O_RDWR);
> >> -    if (streamfd < 0)
> >> -        throw std::runtime_error("failed to open the streaming device ("
> >> +
> >> -                                 streamport + "): " + strerror(errno));
> >> +    Stream stream(streamport, streamfd);
> >> 
> >>     unsigned int frame_count = 0;
> >>     while (!quit_requested) {
> >>         while (!quit_requested && !streaming_requested) {
> >>             if (read_command(true) < 0) {
> >>                 syslog(LOG_ERR, "FAILED to read command\n");
> >> -                goto done;
> >> +                return;
> >>             }
> >>         }
> >> 
> >> @@ -422,16 +436,10 @@ do_capture(const char *streamport, FILE *f_log)
> >>             //usleep(1);
> >>             if (read_command(false) < 0) {
> >>                 syslog(LOG_ERR, "FAILED to read command\n");
> >> -                goto done;
> >> +                return;
> >>             }
> >>         }
> >>     }
> >> -
> >> -done:
> >> -    if (streamfd >= 0) {
> >> -        close(streamfd);
> >> -        streamfd = -1;
> >> -    }
> >> }
> >> 
> >> #define arg_error(...) syslog(LOG_ERR, ## __VA_ARGS__);
> > 

Frediano


More information about the Spice-devel mailing list