// NsEnter locks the current goroutine the OS thread and switches to a // new network namespace. The returned function must be called in order // to restore the previous state and unlock the thread. func NsEnter(ns netns.NsHandle) (func() error, error) { runtime.LockOSThread() origns, err := netns.Get() if err != nil { runtime.UnlockOSThread() return nil, err } err = netns.Set(ns) if err != nil { origns.Close() runtime.UnlockOSThread() return nil, err } return func() error { defer runtime.UnlockOSThread() defer origns.Close() if err := netns.Set(origns); err != nil { return err } return nil }, nil }
//export goMouseCallback func goMouseCallback(name *C.char, event, x, y, flags C.int) { runtime.LockOSThread() defer runtime.UnlockOSThread() winName := C.GoString(name) win, ok := allWindows[winName] if !ok { return } if win.mouseHandle == nil { return } if fa, ok := win.mouseHandle.(func(event, x, y, flags int)); ok { fa(int(event), int(x), int(y), int(flags)) return } if fb, ok := win.mouseHandle.(func(event, x, y, flags int, param ...interface{})); ok { if win.param != nil { fb(int(event), int(x), int(y), int(flags), win.param...) } else { fb(int(event), int(x), int(y), int(flags)) } return } }
func verifySandbox(t *testing.T, s Sandbox, ifaceSuffixes []string) { _, ok := s.(*networkNamespace) if !ok { t.Fatalf("The sandox interface returned is not of type networkNamespace") } origns, err := netns.Get() if err != nil { t.Fatalf("Could not get the current netns: %v", err) } defer origns.Close() f, err := os.OpenFile(s.Key(), os.O_RDONLY, 0) if err != nil { t.Fatalf("Failed top open network namespace path %q: %v", s.Key(), err) } defer f.Close() runtime.LockOSThread() defer runtime.UnlockOSThread() nsFD := f.Fd() if err = netns.Set(netns.NsHandle(nsFD)); err != nil { t.Fatalf("Setting to the namespace pointed to by the sandbox %s failed: %v", s.Key(), err) } defer netns.Set(origns) for _, suffix := range ifaceSuffixes { _, err = netlink.LinkByName(sboxIfaceName + suffix) if err != nil { t.Fatalf("Could not find the interface %s inside the sandbox: %v", sboxIfaceName+suffix, err) } } }
func (v *Reference) SetSymbolicTarget(target string, sig *Signature, msg string) (*Reference, error) { var ptr *C.git_reference ctarget := C.CString(target) defer C.free(unsafe.Pointer(ctarget)) runtime.LockOSThread() defer runtime.UnlockOSThread() csig := sig.toC() defer C.free(unsafe.Pointer(csig)) var cmsg *C.char if msg == "" { cmsg = nil } else { cmsg = C.CString(msg) defer C.free(unsafe.Pointer(cmsg)) } ret := C.git_reference_symbolic_set_target(&ptr, v.ptr, ctarget, csig, cmsg) if ret < 0 { return nil, MakeGitError(ret) } return newReferenceFromC(ptr), nil }
func Clone(url string, path string, options *CloneOptions) (*Repository, error) { repo := new(Repository) curl := C.CString(url) defer C.free(unsafe.Pointer(curl)) cpath := C.CString(path) defer C.free(unsafe.Pointer(cpath)) var copts C.git_clone_options populateCloneOptions(&copts, options) defer freeCheckoutOpts(&copts.checkout_opts) if len(options.CheckoutBranch) != 0 { copts.checkout_branch = C.CString(options.CheckoutBranch) defer C.free(unsafe.Pointer(copts.checkout_branch)) } runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_clone(&repo.ptr, curl, cpath, &copts) if ret < 0 { return nil, MakeGitError(ret) } runtime.SetFinalizer(repo, (*Repository).Free) return repo, nil }
func (b *Branch) Move(newBranchName string, force bool, signature *Signature, msg string) (*Branch, error) { var ptr *C.git_reference cNewBranchName := C.CString(newBranchName) cForce := cbool(force) cSignature, err := signature.toC() if err != nil { return nil, err } defer C.git_signature_free(cSignature) var cmsg *C.char if msg == "" { cmsg = nil } else { cmsg = C.CString(msg) defer C.free(unsafe.Pointer(cmsg)) } runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_branch_move(&ptr, b.Reference.ptr, cNewBranchName, cForce, cSignature, cmsg) if ret < 0 { return nil, MakeGitError(ret) } return newReferenceFromC(ptr, b.repo).Branch(), nil }
// MergeBases retrieves the list of merge bases between two commits. // // If none are found, an empty slice is returned and the error is set // approprately func (r *Repository) MergeBases(one, two *Oid) ([]*Oid, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() var coids C.git_oidarray ret := C.git_merge_bases(&coids, r.ptr, one.toC(), two.toC()) if ret < 0 { return make([]*Oid, 0), MakeGitError(ret) } oids := make([]*Oid, coids.count) hdr := reflect.SliceHeader{ Data: uintptr(unsafe.Pointer(coids.ids)), Len: int(coids.count), Cap: int(coids.count), } goSlice := *(*[]C.git_oid)(unsafe.Pointer(&hdr)) for i, cid := range goSlice { oids[i] = newOidFromC(&cid) } return oids, nil }
func nsInvoke(path string, inNsfunc func(callerFD int) error) error { runtime.LockOSThread() defer runtime.UnlockOSThread() origns, err := netns.Get() if err != nil { return err } defer origns.Close() f, err := os.OpenFile(path, os.O_RDONLY, 0) if err != nil { return fmt.Errorf("failed get network namespace %q: %v", path, err) } defer f.Close() nsFD := f.Fd() if err = netns.Set(netns.NsHandle(nsFD)); err != nil { return err } defer netns.Set(origns) // Invoked after the namespace switch. return inNsfunc(int(origns)) }
// destroy destroys an OpenGL context and unlocks the current goroutine from // its os thread. func (c *contextGL) destroy() { C.CGLUnlockContext(c.ctx) C.CGLSetCurrentContext(nil) C.CGLDestroyContext(c.ctx) c.ctx = nil runtime.UnlockOSThread() }
func (v *Index) AddConflict(ancestor *IndexEntry, our *IndexEntry, their *IndexEntry) error { var cancestor *C.git_index_entry var cour *C.git_index_entry var ctheir *C.git_index_entry if ancestor != nil { cancestor = &C.git_index_entry{} populateCIndexEntry(ancestor, cancestor) defer freeCIndexEntry(cancestor) } if our != nil { cour = &C.git_index_entry{} populateCIndexEntry(our, cour) defer freeCIndexEntry(cour) } if their != nil { ctheir = &C.git_index_entry{} populateCIndexEntry(their, ctheir) defer freeCIndexEntry(ctheir) } runtime.LockOSThread() defer runtime.UnlockOSThread() ecode := C.git_index_conflict_add(v.ptr, cancestor, cour, ctheir) if ecode < 0 { return MakeGitError(ecode) } return nil }
func (v *Index) RemoveAll(pathspecs []string, callback IndexMatchedPathCallback) error { cpathspecs := C.git_strarray{} cpathspecs.count = C.size_t(len(pathspecs)) cpathspecs.strings = makeCStringsFromStrings(pathspecs) defer freeStrarray(&cpathspecs) runtime.LockOSThread() defer runtime.UnlockOSThread() var handle unsafe.Pointer if callback != nil { handle = pointerHandles.Track(callback) defer pointerHandles.Untrack(handle) } ret := C._go_git_index_remove_all( v.ptr, &cpathspecs, handle, ) if ret < 0 { return MakeGitError(ret) } return nil }
func main() { runtime.LockOSThread() defer runtime.UnlockOSThread() defer glfw.Terminate() gorgasm.Verbose = true if !glfw.Init() { panic("Can't init glfw!") } // Enable OpenGL ES 2.0. glfw.WindowHint(glfw.ClientApi, glfw.OpenglEsApi) glfw.WindowHint(glfw.ContextVersionMajor, 2) window, err := glfw.CreateWindow(testlib.Width, testlib.Height, "Gorgasm Test", nil, nil) if err != nil { panic(err) } gorgasm.Init(window) go prettytest.Run(new(testing.T), testlib.NewTestSuite()) for !window.ShouldClose() { glfw.WaitEvents() } }
func MergeFile(ancestor MergeFileInput, ours MergeFileInput, theirs MergeFileInput, options *MergeFileOptions) (*MergeFileResult, error) { var cancestor C.git_merge_file_input var cours C.git_merge_file_input var ctheirs C.git_merge_file_input populateCMergeFileInput(&cancestor, ancestor) defer freeCMergeFileInput(&cancestor) populateCMergeFileInput(&cours, ours) defer freeCMergeFileInput(&cours) populateCMergeFileInput(&ctheirs, theirs) defer freeCMergeFileInput(&ctheirs) var copts *C.git_merge_file_options if options != nil { copts = &C.git_merge_file_options{} ecode := C.git_merge_file_init_options(copts, C.GIT_MERGE_FILE_OPTIONS_VERSION) if ecode < 0 { return nil, MakeGitError(ecode) } populateCMergeFileOptions(copts, *options) } runtime.LockOSThread() defer runtime.UnlockOSThread() var result C.git_merge_file_result ecode := C.git_merge_file(&result, &cancestor, &cours, &ctheirs, copts) if ecode < 0 { return nil, MakeGitError(ecode) } return newMergeFileResultFromC(&result), nil }
func (v *Index) AddAll(pathspecs []string, flags IndexAddOpts, callback IndexMatchedPathCallback) error { cpathspecs := C.git_strarray{} cpathspecs.count = C.size_t(len(pathspecs)) cpathspecs.strings = makeCStringsFromStrings(pathspecs) defer freeStrarray(&cpathspecs) runtime.LockOSThread() defer runtime.UnlockOSThread() var cb *IndexMatchedPathCallback if callback != nil { cb = &callback } ret := C._go_git_index_add_all( v.ptr, &cpathspecs, C.uint(flags), unsafe.Pointer(cb), ) if ret < 0 { return MakeGitError(ret) } return nil }
func Clone(url string, path string, options *CloneOptions) (*Repository, error) { curl := C.CString(url) defer C.free(unsafe.Pointer(curl)) cpath := C.CString(path) defer C.free(unsafe.Pointer(cpath)) copts := (*C.git_clone_options)(C.calloc(1, C.size_t(unsafe.Sizeof(C.git_clone_options{})))) populateCloneOptions(copts, options) defer freeCloneOptions(copts) if len(options.CheckoutBranch) != 0 { copts.checkout_branch = C.CString(options.CheckoutBranch) } runtime.LockOSThread() defer runtime.UnlockOSThread() var ptr *C.git_repository ret := C.git_clone(&ptr, curl, cpath, copts) freeCheckoutOpts(&copts.checkout_opts) if ret < 0 { return nil, MakeGitError(ret) } return newRepositoryFromC(ptr), nil }
// Explicit thread-safe start of libvips. // Only call this function if you've previously shutdown libvips func Initialize() { if C.VIPS_MAJOR_VERSION <= 7 && C.VIPS_MINOR_VERSION < 40 { panic("unsupported libvips version!") } m.Lock() runtime.LockOSThread() defer m.Unlock() defer runtime.UnlockOSThread() err := C.vips_init(C.CString("bimg")) if err != 0 { panic("unable to start vips!") } // Set libvips cache params C.vips_cache_set_max_mem(maxCacheMem) C.vips_cache_set_max(maxCacheSize) // Define a custom thread concurrency limit in libvips (this may generate thread-unsafe issues) // See: https://github.com/jcupitt/libvips/issues/261#issuecomment-92850414 if os.Getenv("VIPS_CONCURRENCY") == "" { C.vips_concurrency_set(1) } // Enable libvips cache tracing if os.Getenv("VIPS_TRACE") != "" { C.vips_enable_cache_set_trace() } initialized = true }
func (v *Reference) SetTarget(target *Oid, sig *Signature, msg string) (*Reference, error) { var ptr *C.git_reference runtime.LockOSThread() defer runtime.UnlockOSThread() csig, err := sig.toC() if err != nil { return nil, err } defer C.git_signature_free(csig) var cmsg *C.char if msg == "" { cmsg = nil } else { cmsg = C.CString(msg) defer C.free(unsafe.Pointer(cmsg)) } ret := C.git_reference_set_target(&ptr, v.ptr, target.toC(), csig, cmsg) if ret < 0 { return nil, MakeGitError(ret) } return newReferenceFromC(ptr, v.repo), nil }
func timeoutIO() { // CancelIO only cancels all pending input and output (I/O) operations that are // issued by the calling thread for the specified file, does not cancel I/O // operations that other threads issue for a file handle. So we need do all timeout // I/O in single OS thread. runtime.LockOSThread() defer runtime.UnlockOSThread() for { o := <-ioChan var e int switch o.f { case read: e = syscall.WSARecv(uint32(o.fd.sysfd), o.pckt.w, 1, o.done, o.flags, &o.pckt.o, nil) case readfrom: e = syscall.WSARecvFrom(uint32(o.fd.sysfd), o.pckt.w, 1, o.done, o.flags, o.rsa, o.size, &o.pckt.o, nil) case write: e = syscall.WSASend(uint32(o.fd.sysfd), o.pckt.w, 1, o.done, uint32(0), &o.pckt.o, nil) case writeto: e = syscall.WSASendto(uint32(o.fd.sysfd), o.pckt.w, 1, o.done, 0, *o.sa, &o.pckt.o, nil) case cancel: _, e = syscall.CancelIo(uint32(o.fd.sysfd)) } o.c <- e } }
func setupNetNs(nsPath string) (*os.Process, error) { runtime.LockOSThread() defer runtime.UnlockOSThread() origns, err := netns.Get() if err != nil { return nil, err } defer origns.Close() f, err := os.OpenFile(nsPath, os.O_RDONLY, 0) if err != nil { return nil, fmt.Errorf("failed to get network namespace %q: %v", nsPath, err) } defer f.Close() nsFD := f.Fd() if err := netns.Set(netns.NsHandle(nsFD)); err != nil { return nil, fmt.Errorf("failed to set network namespace %q: %v", nsPath, err) } defer netns.Set(origns) cmd := exec.Command("/bin/sh", "-c", "while true; do sleep 1; done") if err := cmd.Start(); err != nil { return nil, fmt.Errorf("failed to start netns process: %v", err) } return cmd.Process, nil }
// Do takes a function which it will call in the network namespace specified by nsName. // The goroutine that calls this will lock itself to its current OS thread, hop // namespaces, call the given function, hop back to its original namespace, and then // unlock itself from its current OS thread. // Do returns an error if an error occurs at any point besides in the invocation of // the given function. // The caller should check both the error of Do and any errors from the given function call. // // The callback function is expected to do something simple such as just // creating a socket / opening a connection, as it's not desirable to start // complex logic in a goroutine that is pinned to the current OS thread. // Also any goroutine started from the callback function may or may not // execute in the desired namespace. func Do(nsName string, cb Callback) error { // If destNS is empty, the function is called in the caller's namespace if nsName == "" { cb() return nil } // Get the file descriptor to the current namespace currNsFd, err := getNs(selfNsFile) if os.IsNotExist(err) { return fmt.Errorf("File descriptor to current namespace does not exist: %s", err) } else if err != nil { return fmt.Errorf("Failed to open %s: %s", selfNsFile, err) } defer currNsFd.close() runtime.LockOSThread() defer runtime.UnlockOSThread() // Jump to the new network namespace if err := setNsByName(nsName); err != nil { return fmt.Errorf("Failed to set the namespace to %s: %s", nsName, err) } // Call the given function cb() // Come back to the original namespace if err = setNs(currNsFd); err != nil { return fmt.Errorf("Failed to return to the original namespace: %s", err) } return nil }
func TestGetNewSetDelete(t *testing.T) { runtime.LockOSThread() defer runtime.UnlockOSThread() origns, err := Get() if err != nil { t.Fatal(err) } newns, err := New() if err != nil { t.Fatal(err) } if origns.Equal(newns) { t.Fatal("New ns failed") } if err := Set(origns); err != nil { t.Fatal(err) } newns.Close() if newns.IsOpen() { t.Fatal("newns still open after close", newns) } ns, err := Get() if err != nil { t.Fatal(err) } if !ns.Equal(origns) { t.Fatal("Reset ns failed", origns, newns, ns) } }
// lookupProtocol looks up IP protocol name and returns correspondent protocol number. func lookupProtocol(ctx context.Context, name string) (int, error) { // GetProtoByName return value is stored in thread local storage. // Start new os thread before the call to prevent races. type result struct { proto int err error } ch := make(chan result) // unbuffered go func() { acquireThread() defer releaseThread() runtime.LockOSThread() defer runtime.UnlockOSThread() proto, err := getprotobyname(name) select { case ch <- result{proto: proto, err: err}: case <-ctx.Done(): } }() select { case r := <-ch: if r.err != nil { if proto, err := lookupProtocolMap(name); err == nil { return proto, nil } r.err = &DNSError{Err: r.err.Error(), Name: name} } return r.proto, r.err case <-ctx.Done(): return 0, mapErr(ctx.Err()) } }
func (repo *Repository) CreateBranch(branchName string, target *Commit, force bool, signature *Signature, msg string) (*Branch, error) { ref := new(Reference) cBranchName := C.CString(branchName) cForce := cbool(force) cSignature, err := signature.toC() if err != nil { return nil, err } defer C.git_signature_free(cSignature) var cmsg *C.char if msg == "" { cmsg = nil } else { cmsg = C.CString(msg) defer C.free(unsafe.Pointer(cmsg)) } runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_branch_create(&ref.ptr, repo.ptr, cBranchName, target.cast_ptr, cForce, cSignature, cmsg) if ret < 0 { return nil, MakeGitError(ret) } return ref.Branch(), nil }
func main() { runtime.LockOSThread() defer runtime.UnlockOSThread() defer glfw.Terminate() mandala.Verbose = true if !glfw.Init() { panic("Can't init glfw!") } // Enable OpenGL ES 2.0. glfw.WindowHint(glfw.ClientApi, glfw.OpenglEsApi) glfw.WindowHint(glfw.ContextVersionMajor, 2) window, err := glfw.CreateWindow(Width, Height, "gltext black-box testing", nil, nil) if err != nil { panic(err) } glfw.SwapInterval(0) mandala.Init(window) go prettytest.Run(new(testing.T), testlib.NewTestSuite(outputPath)) for !window.ShouldClose() { glfw.WaitEvents() } }
// goCallbackExit gets invoked from within xhyve.c whenever a trap // suspending the VM is triggered. This is so we can clean up resources // in Go land, restore terminal settings and allow the goroutine to be scheduled // on multiple OS threads again by Go's scheduler. //export goCallbackExit func goCallbackExit(status C.int) { exitStatus := map[int]string{ 0: "Reset", 1: "PowerOFF", 2: "Halt", 3: "TripleFault", 100: "Internal error", } // Restores stty settings to the values that existed before running xhyve. setTermios(termios) fmt.Printf("VM has been suspended by %s event\n", exitStatus[int(status)]) fmt.Printf("Releasing allocated memory from Go land... ") for _, arg := range argv { C.free(unsafe.Pointer(arg)) } fmt.Println("done") // Turns exit flag On for mevent busy loop so that the next time kevent // receives an event, mevent handles it and exits the loop. fmt.Print("Signaling xhyve mevent dispatch loop to exit... ") C.exit_mevent_dispatch_loop = true // Forces kevent() to exit by using the self-pipe trick. C.mevent_exit() fmt.Println("done") // Allows Go's scheduler to move the goroutine to a different OS thread. runtime.UnlockOSThread() }
func (b *Branch) Move(newBranchName string, force bool, signature *Signature, msg string) (*Branch, error) { newBranch := new(Branch) cNewBranchName := C.CString(newBranchName) cForce := cbool(force) cSignature := signature.toC() defer C.git_signature_free(cSignature) var cmsg *C.char if msg == "" { cmsg = nil } else { cmsg = C.CString(msg) defer C.free(unsafe.Pointer(cmsg)) } runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_branch_move(&newBranch.ptr, b.ptr, cNewBranchName, cForce, cSignature, cmsg) if ret < 0 { return nil, MakeGitError(ret) } return newBranch, nil }
func (v *Reference) Rename(name string, force bool, sig *Signature, msg string) (*Reference, error) { var ptr *C.git_reference cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) csig := sig.toC() defer C.free(unsafe.Pointer(csig)) var cmsg *C.char if msg == "" { cmsg = nil } else { cmsg = C.CString(msg) defer C.free(unsafe.Pointer(cmsg)) } runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_reference_rename(&ptr, v.ptr, cname, cbool(force), csig, cmsg) if ret < 0 { return nil, MakeGitError(ret) } return newReferenceFromC(ptr), nil }
func (c *Config) NewMultivarIterator(name, regexp string) (*ConfigIterator, error) { cname := C.CString(name) defer C.free(unsafe.Pointer(cname)) var cregexp *C.char if regexp == "" { cregexp = nil } else { cregexp = C.CString(regexp) defer C.free(unsafe.Pointer(cregexp)) } iter := new(ConfigIterator) runtime.LockOSThread() defer runtime.UnlockOSThread() ret := C.git_config_multivar_iterator_new(&iter.ptr, c.ptr, cname, cregexp) if ret < 0 { return nil, MakeGitError(ret) } runtime.SetFinalizer(iter, (*ConfigIterator).Free) return iter, nil }
func checkSandbox(t *testing.T, info libnetwork.EndpointInfo) { origns, err := netns.Get() if err != nil { t.Fatalf("Could not get the current netns: %v", err) } defer origns.Close() key := info.Sandbox().Key() f, err := os.OpenFile(key, os.O_RDONLY, 0) if err != nil { t.Fatalf("Failed to open network namespace path %q: %v", key, err) } defer f.Close() runtime.LockOSThread() defer runtime.UnlockOSThread() nsFD := f.Fd() if err = netns.Set(netns.NsHandle(nsFD)); err != nil { t.Fatalf("Setting to the namespace pointed to by the sandbox %s failed: %v", key, err) } defer netns.Set(origns) _, err = netlink.LinkByName("eth0") if err != nil { t.Fatalf("Could not find the interface eth0 inside the sandbox: %v", err) } _, err = netlink.LinkByName("eth1") if err != nil { t.Fatalf("Could not find the interface eth1 inside the sandbox: %v", err) } }
func (udp *udpProxySocket) getBackendConn(activeClients *clientCache, cliAddr net.Addr, proxier *Proxier, service string, timeout time.Duration) (net.Conn, error) { activeClients.mu.Lock() defer activeClients.mu.Unlock() svrConn, found := activeClients.clients[cliAddr.String()] if !found { // TODO: This could spin up a new goroutine to make the outbound connection, // and keep accepting inbound traffic. glog.Infof("New UDP connection from %s", cliAddr) ns, endpoint, err := proxier.loadBalancer.NextEndpoint(service, cliAddr) if err != nil { glog.Errorf("Couldn't find an endpoint for %s %v", service, err) return nil, err } glog.Infof("Mapped service %s to endpoint %s", service, endpoint) if ns.IsOpen() { glog.Infof("Using namespace %v for endpoint %s", ns, endpoint) runtime.LockOSThread() netns.Set(ns) defer runtime.UnlockOSThread() } svrConn, err = retryDial("udp", endpoint, endpointDialTimeout) if err != nil { // TODO: Try another endpoint? glog.Errorf("Dial failed: %v", err) return nil, err } activeClients.clients[cliAddr.String()] = svrConn go func(cliAddr net.Addr, svrConn net.Conn, activeClients *clientCache, timeout time.Duration) { defer util.HandleCrash() udp.proxyClient(cliAddr, svrConn, activeClients, timeout) }(cliAddr, svrConn, activeClients, timeout) } return svrConn, nil }