From nobody Sun Feb 8 05:54:51 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) client-ip=209.132.183.28; envelope-from=libvir-list-bounces@redhat.com; helo=mx1.redhat.com; Authentication-Results: mx.zohomail.com; spf=pass (zoho.com: domain of redhat.com designates 209.132.183.28 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com Return-Path: Received: from mx1.redhat.com (mx1.redhat.com [209.132.183.28]) by mx.zohomail.com with SMTPS id 1531747502532983.572550780777; Mon, 16 Jul 2018 06:25:02 -0700 (PDT) Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 2CCBF4E358; Mon, 16 Jul 2018 13:25:01 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id EB59160C4E; Mon, 16 Jul 2018 13:25:00 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id 912171853DA2; Mon, 16 Jul 2018 13:25:00 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx04.intmail.prod.int.rdu2.redhat.com [10.11.54.4]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id w6GDOoRY028166 for ; Mon, 16 Jul 2018 09:24:50 -0400 Received: by smtp.corp.redhat.com (Postfix) id 6B8B42027047; Mon, 16 Jul 2018 13:24:50 +0000 (UTC) Received: from t460.redhat.com (unknown [10.33.36.75]) by smtp.corp.redhat.com (Postfix) with ESMTP id 639E42026D65; Mon, 16 Jul 2018 13:24:48 +0000 (UTC) From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Date: Mon, 16 Jul 2018 14:24:08 +0100 Message-Id: <20180716132423.10354-23-berrange@redhat.com> In-Reply-To: <20180716132423.10354-1-berrange@redhat.com> References: <20180716132423.10354-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.78 on 10.11.54.4 X-loop: libvir-list@redhat.com Subject: [libvirt] [go PATCH 22/37] stream: fix error reporting thread safety X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.12 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.38]); Mon, 16 Jul 2018 13:25:01 +0000 (UTC) X-ZohoMail: RSF_0 Z_629925259 SPT_0 Create wrapper functions for each stream C API that accepts a virErrorPtr parameter. This avoids accessing a thread local from a goroutine which may race with other goroutines doing native API calls in the same OS thread. Signed-off-by: Daniel P. Berrang=C3=A9 --- stream.go | 80 +++++++++------- stream_wrapper.go | 231 +++++++++++++++++++++++++++++++++++++++------- stream_wrapper.h | 84 +++++++++++++---- 3 files changed, 312 insertions(+), 83 deletions(-) diff --git a/stream.go b/stream.go index c5c1ef7..515ae08 100644 --- a/stream.go +++ b/stream.go @@ -64,9 +64,10 @@ type Stream struct { =20 // See also https://libvirt.org/html/libvirt-libvirt-stream.html#virStream= Abort func (v *Stream) Abort() error { - result :=3D C.virStreamAbort(v.ptr) + var err C.virError + result :=3D C.virStreamAbortWrapper(v.ptr, &err) if result =3D=3D -1 { - return GetLastError() + return makeError(&err) } =20 return nil @@ -74,9 +75,10 @@ func (v *Stream) Abort() error { =20 // See also https://libvirt.org/html/libvirt-libvirt-stream.html#virStream= Finish func (v *Stream) Finish() error { - result :=3D C.virStreamFinish(v.ptr) + var err C.virError + result :=3D C.virStreamFinishWrapper(v.ptr, &err) if result =3D=3D -1 { - return GetLastError() + return makeError(&err) } =20 return nil @@ -84,27 +86,30 @@ func (v *Stream) Finish() error { =20 // See also https://libvirt.org/html/libvirt-libvirt-stream.html#virStream= Free func (v *Stream) Free() error { - ret :=3D C.virStreamFree(v.ptr) + var err C.virError + ret :=3D C.virStreamFreeWrapper(v.ptr, &err) if ret =3D=3D -1 { - return GetLastError() + return makeError(&err) } return nil } =20 // See also https://libvirt.org/html/libvirt-libvirt-stream.html#virStream= Ref func (c *Stream) Ref() error { - ret :=3D C.virStreamRef(c.ptr) + var err C.virError + ret :=3D C.virStreamRefWrapper(c.ptr, &err) if ret =3D=3D -1 { - return GetLastError() + return makeError(&err) } return nil } =20 // See also https://libvirt.org/html/libvirt-libvirt-stream.html#virStream= Recv func (v *Stream) Recv(p []byte) (int, error) { - n :=3D C.virStreamRecv(v.ptr, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(= len(p))) + var err C.virError + n :=3D C.virStreamRecvWrapper(v.ptr, (*C.char)(unsafe.Pointer(&p[0])), C.= size_t(len(p)), &err) if n < 0 { - return 0, GetLastError() + return 0, makeError(&err) } if n =3D=3D 0 { return 0, io.EOF @@ -119,9 +124,10 @@ func (v *Stream) RecvFlags(p []byte, flags StreamRecvF= lagsValues) (int, error) { return 0, GetNotImplementedError("virStreamRecvFlags") } =20 - n :=3D C.virStreamRecvFlagsWrapper(v.ptr, (*C.char)(unsafe.Pointer(&p[0])= ), C.size_t(len(p)), C.uint(flags)) + var err C.virError + n :=3D C.virStreamRecvFlagsWrapper(v.ptr, (*C.char)(unsafe.Pointer(&p[0])= ), C.size_t(len(p)), C.uint(flags), &err) if n < 0 { - return 0, GetLastError() + return 0, makeError(&err) } if n =3D=3D 0 { return 0, io.EOF @@ -137,9 +143,10 @@ func (v *Stream) RecvHole(flags uint) (int64, error) { } =20 var len C.longlong - ret :=3D C.virStreamRecvHoleWrapper(v.ptr, &len, C.uint(flags)) + var err C.virError + ret :=3D C.virStreamRecvHoleWrapper(v.ptr, &len, C.uint(flags), &err) if ret < 0 { - return 0, GetLastError() + return 0, makeError(&err) } =20 return int64(len), nil @@ -147,9 +154,10 @@ func (v *Stream) RecvHole(flags uint) (int64, error) { =20 // See also https://libvirt.org/html/libvirt-libvirt-stream.html#virStream= Send func (v *Stream) Send(p []byte) (int, error) { - n :=3D C.virStreamSend(v.ptr, (*C.char)(unsafe.Pointer(&p[0])), C.size_t(= len(p))) + var err C.virError + n :=3D C.virStreamSendWrapper(v.ptr, (*C.char)(unsafe.Pointer(&p[0])), C.= size_t(len(p)), &err) if n < 0 { - return 0, GetLastError() + return 0, makeError(&err) } if n =3D=3D 0 { return 0, io.EOF @@ -164,9 +172,10 @@ func (v *Stream) SendHole(len int64, flags uint32) err= or { return GetNotImplementedError("virStreamSendHole") } =20 - ret :=3D C.virStreamSendHoleWrapper(v.ptr, C.longlong(len), C.uint(flags)) + var err C.virError + ret :=3D C.virStreamSendHoleWrapper(v.ptr, C.longlong(len), C.uint(flags)= , &err) if ret < 0 { - return GetLastError() + return makeError(&err) } =20 return nil @@ -220,10 +229,11 @@ func (v *Stream) RecvAll(handler StreamSinkFunc) erro= r { =20 callbackID :=3D registerCallbackId(handler) =20 - ret :=3D C.virStreamRecvAllWrapper(v.ptr, (C.int)(callbackID)) + var err C.virError + ret :=3D C.virStreamRecvAllWrapper(v.ptr, (C.int)(callbackID), &err) freeCallbackId(callbackID) if ret =3D=3D -1 { - return GetLastError() + return makeError(&err) } =20 return nil @@ -238,11 +248,12 @@ func (v *Stream) SparseRecvAll(handler StreamSinkFunc= , holeHandler StreamSinkHol callbackID :=3D registerCallbackId(handler) holeCallbackID :=3D registerCallbackId(holeHandler) =20 - ret :=3D C.virStreamSparseRecvAllWrapper(v.ptr, (C.int)(callbackID), (C.i= nt)(holeCallbackID)) + var err C.virError + ret :=3D C.virStreamSparseRecvAllWrapper(v.ptr, (C.int)(callbackID), (C.i= nt)(holeCallbackID), &err) freeCallbackId(callbackID) freeCallbackId(holeCallbackID) if ret =3D=3D -1 { - return GetLastError() + return makeError(&err) } =20 return nil @@ -325,10 +336,11 @@ func (v *Stream) SendAll(handler StreamSourceFunc) er= ror { =20 callbackID :=3D registerCallbackId(handler) =20 - ret :=3D C.virStreamSendAllWrapper(v.ptr, (C.int)(callbackID)) + var err C.virError + ret :=3D C.virStreamSendAllWrapper(v.ptr, (C.int)(callbackID), &err) freeCallbackId(callbackID) if ret =3D=3D -1 { - return GetLastError() + return makeError(&err) } =20 return nil @@ -344,12 +356,13 @@ func (v *Stream) SparseSendAll(handler StreamSourceFu= nc, holeHandler StreamSourc holeCallbackID :=3D registerCallbackId(holeHandler) skipCallbackID :=3D registerCallbackId(skipHandler) =20 - ret :=3D C.virStreamSparseSendAllWrapper(v.ptr, (C.int)(callbackID), (C.i= nt)(holeCallbackID), (C.int)(skipCallbackID)) + var err C.virError + ret :=3D C.virStreamSparseSendAllWrapper(v.ptr, (C.int)(callbackID), (C.i= nt)(holeCallbackID), (C.int)(skipCallbackID), &err) freeCallbackId(callbackID) freeCallbackId(holeCallbackID) freeCallbackId(skipCallbackID) if ret =3D=3D -1 { - return GetLastError() + return makeError(&err) } =20 return nil @@ -361,9 +374,10 @@ type StreamEventCallback func(*Stream, StreamEventType) func (v *Stream) EventAddCallback(events StreamEventType, callback StreamE= ventCallback) error { callbackID :=3D registerCallbackId(callback) =20 - ret :=3D C.virStreamEventAddCallbackWrapper(v.ptr, (C.int)(events), (C.in= t)(callbackID)) + var err C.virError + ret :=3D C.virStreamEventAddCallbackWrapper(v.ptr, (C.int)(events), (C.in= t)(callbackID), &err) if ret =3D=3D -1 { - return GetLastError() + return makeError(&err) } =20 return nil @@ -383,9 +397,10 @@ func streamEventCallback(st C.virStreamPtr, events int= , callbackID int) { =20 // See also https://libvirt.org/html/libvirt-libvirt-stream.html#virStream= EventUpdateCallback func (v *Stream) EventUpdateCallback(events StreamEventType) error { - ret :=3D C.virStreamEventUpdateCallback(v.ptr, (C.int)(events)) + var err C.virError + ret :=3D C.virStreamEventUpdateCallbackWrapper(v.ptr, (C.int)(events), &e= rr) if ret =3D=3D -1 { - return GetLastError() + return makeError(&err) } =20 return nil @@ -393,9 +408,10 @@ func (v *Stream) EventUpdateCallback(events StreamEven= tType) error { =20 // See also https://libvirt.org/html/libvirt-libvirt-stream.html#virStream= EventRemoveCallback func (v *Stream) EventRemoveCallback() error { - ret :=3D C.virStreamEventRemoveCallback(v.ptr) + var err C.virError + ret :=3D C.virStreamEventRemoveCallbackWrapper(v.ptr, &err) if ret =3D=3D -1 { - return GetLastError() + return makeError(&err) } =20 return nil diff --git a/stream_wrapper.go b/stream_wrapper.go index 90cc110..e563a74 100644 --- a/stream_wrapper.go +++ b/stream_wrapper.go @@ -81,84 +81,251 @@ static int streamSinkHoleCallbackHelper(virStreamPtr s= t, long long length, void return streamSinkHoleCallback(st, length, cbdata->holeCallbackID); } =20 -int virStreamSendAllWrapper(virStreamPtr st, int callbackID) +int +virStreamAbortWrapper(virStreamPtr stream, + virErrorPtr err) +{ + int ret =3D virStreamAbort(stream); + if (ret < 0) { + virCopyLastError(err); + } + return ret; +} + + +void +streamEventCallback(virStreamPtr st, int events, int callbackID); + +static void +streamEventCallbackHelper(virStreamPtr st, int events, void *opaque) +{ + streamEventCallback(st, events, (int)(intptr_t)opaque); +} + +int +virStreamEventAddCallbackWrapper(virStreamPtr stream, + int events, + int callbackID, + virErrorPtr err) +{ + int ret =3D virStreamEventAddCallback(stream, events, streamEventCallb= ackHelper, (void *)(intptr_t)callbackID, NULL); + if (ret < 0) { + virCopyLastError(err); + } + return ret; +} + + +int +virStreamEventRemoveCallbackWrapper(virStreamPtr stream, + virErrorPtr err) +{ + int ret =3D virStreamEventRemoveCallback(stream); + if (ret < 0) { + virCopyLastError(err); + } + return ret; +} + + +int +virStreamEventUpdateCallbackWrapper(virStreamPtr stream, + int events, + virErrorPtr err) +{ + int ret =3D virStreamEventUpdateCallback(stream, events); + if (ret < 0) { + virCopyLastError(err); + } + return ret; +} + + +int +virStreamFinishWrapper(virStreamPtr stream, + virErrorPtr err) +{ + int ret =3D virStreamFinish(stream); + if (ret < 0) { + virCopyLastError(err); + } + return ret; +} + + +int +virStreamFreeWrapper(virStreamPtr stream, + virErrorPtr err) +{ + int ret =3D virStreamFree(stream); + if (ret < 0) { + virCopyLastError(err); + } + return ret; +} + + +int +virStreamRecvWrapper(virStreamPtr stream, + char *data, + size_t nbytes, + virErrorPtr err) +{ + int ret =3D virStreamRecv(stream, data, nbytes); + if (ret < 0) { + virCopyLastError(err); + } + return ret; +} + + +int +virStreamRecvAllWrapper(virStreamPtr stream, + int callbackID, + virErrorPtr err) { struct CallbackData cbdata =3D { .callbackID =3D callbackID }; - return virStreamSendAll(st, streamSourceCallbackHelper, &cbdata); + int ret =3D virStreamRecvAll(stream, streamSinkCallbackHelper, &cbdata= ); + if (ret < 0) { + virCopyLastError(err); + } + return ret; } =20 -int virStreamSparseSendAllWrapper(virStreamPtr st, int callbackID, int hol= eCallbackID, int skipCallbackID) + +int +virStreamRecvFlagsWrapper(virStreamPtr stream, + char *data, + size_t nbytes, + unsigned int flags, + virErrorPtr err) { - struct CallbackData cbdata =3D { .callbackID =3D callbackID, .holeCall= backID =3D holeCallbackID, .skipCallbackID =3D skipCallbackID }; #if LIBVIR_VERSION_NUMBER < 3004000 assert(0); // Caller should have checked version #else - return virStreamSparseSendAll(st, streamSourceCallbackHelper, streamSo= urceHoleCallbackHelper, streamSourceSkipCallbackHelper, &cbdata); + int ret =3D virStreamRecvFlags(stream, data, nbytes, flags); + if (ret < 0) { + virCopyLastError(err); + } + return ret; #endif } =20 =20 -int virStreamRecvAllWrapper(virStreamPtr st, int callbackID) -{ - struct CallbackData cbdata =3D { .callbackID =3D callbackID }; - return virStreamRecvAll(st, streamSinkCallbackHelper, &cbdata); -} - -int virStreamSparseRecvAllWrapper(virStreamPtr st, int callbackID, int hol= eCallbackID) +int +virStreamRecvHoleWrapper(virStreamPtr stream, + long long *length, + unsigned int flags, + virErrorPtr err) { - struct CallbackData cbdata =3D { .callbackID =3D callbackID, .holeCall= backID =3D holeCallbackID }; #if LIBVIR_VERSION_NUMBER < 3004000 assert(0); // Caller should have checked version #else - return virStreamSparseRecvAll(st, streamSinkCallbackHelper, streamSink= HoleCallbackHelper, &cbdata); + int ret =3D virStreamRecvHole(stream, length, flags); + if (ret < 0) { + virCopyLastError(err); + } + return ret; #endif } =20 -void streamEventCallback(virStreamPtr st, int events, int callbackID); =20 -static void streamEventCallbackHelper(virStreamPtr st, int events, void *o= paque) +int +virStreamRefWrapper(virStreamPtr stream, + virErrorPtr err) { - streamEventCallback(st, events, (int)(intptr_t)opaque); + int ret =3D virStreamRef(stream); + if (ret < 0) { + virCopyLastError(err); + } + return ret; } =20 -int virStreamEventAddCallbackWrapper(virStreamPtr st, int events, int call= backID) + +int +virStreamSendWrapper(virStreamPtr stream, + const char *data, + size_t nbytes, + virErrorPtr err) { - return virStreamEventAddCallback(st, events, streamEventCallbackHelper= , (void *)(intptr_t)callbackID, NULL); + int ret =3D virStreamSend(stream, data, nbytes); + if (ret < 0) { + virCopyLastError(err); + } + return ret; } =20 -int virStreamRecvFlagsWrapper(virStreamPtr st, - char *data, - size_t nbytes, - unsigned int flags) + +int +virStreamSendAllWrapper(virStreamPtr stream, + int callbackID, + virErrorPtr err) +{ + struct CallbackData cbdata =3D { .callbackID =3D callbackID }; + int ret =3D virStreamSendAll(stream, streamSourceCallbackHelper, &cbda= ta); + if (ret < 0) { + virCopyLastError(err); + } + return ret; +} + + +int +virStreamSendHoleWrapper(virStreamPtr stream, + long long length, + unsigned int flags, + virErrorPtr err) { #if LIBVIR_VERSION_NUMBER < 3004000 assert(0); // Caller should have checked version #else - return virStreamRecvFlags(st, data, nbytes, flags); + int ret =3D virStreamSendHole(stream, length, flags); + if (ret < 0) { + virCopyLastError(err); + } + return ret; #endif } =20 -int virStreamSendHoleWrapper(virStreamPtr st, - long long length, - unsigned int flags) + +int +virStreamSparseRecvAllWrapper(virStreamPtr stream, + int callbackID, + int holeCallbackID, + virErrorPtr err) { + struct CallbackData cbdata =3D { .callbackID =3D callbackID, .holeCall= backID =3D holeCallbackID }; #if LIBVIR_VERSION_NUMBER < 3004000 assert(0); // Caller should have checked version #else - return virStreamSendHole(st, length, flags); + int ret =3D virStreamSparseRecvAll(stream, streamSinkCallbackHelper, s= treamSinkHoleCallbackHelper, &cbdata); + if (ret < 0) { + virCopyLastError(err); + } + return ret; #endif } =20 -int virStreamRecvHoleWrapper(virStreamPtr st, - long long *length, - unsigned int flags) + +int +virStreamSparseSendAllWrapper(virStreamPtr stream, + int callbackID, + int holeCallbackID, + int skipCallbackID, + virErrorPtr err) { + struct CallbackData cbdata =3D { .callbackID =3D callbackID, .holeCall= backID =3D holeCallbackID, .skipCallbackID =3D skipCallbackID }; #if LIBVIR_VERSION_NUMBER < 3004000 assert(0); // Caller should have checked version #else - return virStreamRecvHole(st, length, flags); + int ret =3D virStreamSparseSendAll(stream, streamSourceCallbackHelper,= streamSourceHoleCallbackHelper, streamSourceSkipCallbackHelper, &cbdata); + if (ret < 0) { + virCopyLastError(err); + } + return ret; #endif } =20 + */ import "C" diff --git a/stream_wrapper.h b/stream_wrapper.h index 5484441..b9c6e57 100644 --- a/stream_wrapper.h +++ b/stream_wrapper.h @@ -32,43 +32,89 @@ #include "stream_compat.h" =20 int -virStreamSendAllWrapper(virStreamPtr st, - int callbackID); +virStreamAbortWrapper(virStreamPtr stream, + virErrorPtr err); =20 int -virStreamRecvAllWrapper(virStreamPtr st, - int callbackID); +virStreamEventAddCallbackWrapper(virStreamPtr st, + int events, + int callbackID, + virErrorPtr err); =20 int -virStreamSparseSendAllWrapper(virStreamPtr st, - int callbackID, - int holeCallbackID, - int skipCallbackID); +virStreamEventRemoveCallbackWrapper(virStreamPtr stream, + virErrorPtr err); =20 int -virStreamSparseRecvAllWrapper(virStreamPtr st, - int callbackID, - int holeCallbackID); +virStreamEventUpdateCallbackWrapper(virStreamPtr stream, + int events, + virErrorPtr err); =20 int -virStreamEventAddCallbackWrapper(virStreamPtr st, - int events, - int callbackID); +virStreamFinishWrapper(virStreamPtr stream, + virErrorPtr err); + +int +virStreamFreeWrapper(virStreamPtr stream, + virErrorPtr err); + +int +virStreamRecvWrapper(virStreamPtr stream, + char *data, + size_t nbytes, + virErrorPtr err); + +int +virStreamRecvAllWrapper(virStreamPtr st, + int callbackID, + virErrorPtr err); =20 int virStreamRecvFlagsWrapper(virStreamPtr st, char *data, size_t nbytes, - unsigned int flags); + unsigned int flags, + virErrorPtr err); + +int +virStreamRecvHoleWrapper(virStreamPtr, + long long *length, + unsigned int flags, + virErrorPtr err); + +int +virStreamRefWrapper(virStreamPtr stream, + virErrorPtr err); + +int +virStreamSendWrapper(virStreamPtr stream, + const char *data, + size_t nbytes, + virErrorPtr err); + +int +virStreamSendAllWrapper(virStreamPtr st, + int callbackID, + virErrorPtr err); =20 int virStreamSendHoleWrapper(virStreamPtr st, long long length, - unsigned int flags); + unsigned int flags, + virErrorPtr err); =20 int -virStreamRecvHoleWrapper(virStreamPtr, - long long *length, - unsigned int flags); +virStreamSparseRecvAllWrapper(virStreamPtr st, + int callbackID, + int holeCallbackID, + virErrorPtr err); + +int +virStreamSparseSendAllWrapper(virStreamPtr st, + int callbackID, + int holeCallbackID, + int skipCallbackID, + virErrorPtr err); + =20 #endif /* LIBVIRT_GO_STREAM_WRAPPER_H__ */ --=20 2.17.1 -- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list