[libvirt] [RFC] Simplifying usage of {Enter, Exit}Monitor and {Begin/End}Job
Daniel P. Berrange
berrange at redhat.com
Thu Oct 22 12:52:29 UTC 2015
On Thu, Oct 22, 2015 at 01:47:28PM +0200, Jiri Denemark wrote:
> Hi all.
>
> Looking at the qemu driver code, we have a lot of code with the
> following pattern:
>
> if (doSomething() < 0)
> goto cleanup;
>
> if (qemuDomainObjBeginJob() < 0)
> goto cleanup;
>
> if (doSomethingElse() < 0)
> goto endjob;
>
> qemuDomainObjEnterMonitor();
>
> if (qemuMonitorSomething() < 0) {
> qemuDomainObjExitMonitor();
> goto endjob;
> }
>
> if (qemuMonitorSomethingElse() < 0) {
> qemuDomainObjExitMonitor();
> goto endjob;
> }
>
> if (qemuDomainObjExitMonitor() < 0)
> goto endjob;
>
> ...
>
> ret = 0;
>
> endjob:
> qemuDomainObjEndJob();
>
> cleanup:
> ...
> return ret;
>
> Sometimes qemuDomainObjExitMonitor is in its own label instead of being
> explicitly called on every single error path. Sometimes
> qemuDomainObjEndJob is called explicitly followed by goto cleanup. In
> either case, it's pretty easy to get this wrong. It's too easy to jump
> to a wrong label (especially when moving code around) or forget to call
> the appropriate exit function before jumping to a label.
>
> So what if we make the code more robust by changing who needs to track
> whether we are in a monitor or have a job. Now it's the caller that
> tracks it while I think we could teach the job/monitor APIs themselves
> to track the state:
>
> bool inJob = false;
> bool inMonitor = false;
>
> if (doSomething() < 0)
> goto cleanup;
>
> if (qemuDomainObjBeginJob(..., &inJob) < 0)
> goto cleanup;
>
> if (doSomethingElse() < 0)
> goto cleanup;
>
> qemuDomainObjEnterMonitor(..., &inMonitor);
>
> if (qemuMonitorSomething() < 0)
> goto cleanup;
>
> if (qemuMonitorSomethingElse() < 0)
> goto cleanup;
>
> if (qemuDomainObjExitMonitor(..., &inMonitor) < 0)
> goto cleanup;
>
> ...
>
> ret = 0;
>
> cleanup:
> if (qemuDomainObjExitMonitor(..., &inMonitor) < 0)
> ret = -1;
> qemuDomainObjEndJob(..., &inJob);
> ...
> return ret;
>
>
> It's not a lot shorter or longer but it saves us from jumping to
> different labels and it makes sure we always exit the monitor and end
> the job.
>
> So is it worth the effort or do you thing it's even worse than before or
> do you have any other ideas?
On a related topic, we don't have great error reporting in the (usually
unlikely) scenario that we get a stuck job / timeout. I've long thought
it could be desirable to record some metadata when we start jobs, such
as the __FUNC__ of the method which started the job, so when we report
an error we can include that info as a diagnostic aid. This would
have to be against the qemuDomainObjPrivPtr struct. THis makes me
think that using the separate bool inJob/inMonitor stack variables
is not required.
We could just add
int threadid;
bool inJob;
bool inMonitor;
const char *jobfunc;
to qemuDomainObjPrivPtr. That way you don't need to modify the
Enter/Exit functions to add extra arguments - we just track
everything internally. When exiting, we'd compare against the
threadid, to make sure we don't accidentally relaase a different
thread's job.
Regards,
Daniel
--
|: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :|
|: http://libvirt.org -o- http://virt-manager.org :|
|: http://autobuild.org -o- http://search.cpan.org/~danberr/ :|
|: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
More information about the libvir-list
mailing list