vendor/golang.org/x/sys/unix/syscall_solaris.go
changeset 262 8d3354485fc3
parent 260 445e01aede7e
child 265 05c40b36d3b2
equal deleted inserted replaced
261:270cc4dda0c5 262:8d3354485fc3
   748 	// the user hasn't requested/received it yet.
   748 	// the user hasn't requested/received it yet.
   749 	// If the user wants to port_dissociate before the event has been processed,
   749 	// If the user wants to port_dissociate before the event has been processed,
   750 	// we should handle things gracefully. To do so, we need to keep an extra
   750 	// we should handle things gracefully. To do so, we need to keep an extra
   751 	// reference to the cookie around until the event is processed
   751 	// reference to the cookie around until the event is processed
   752 	// thus the otherwise seemingly extraneous "cookies" map
   752 	// thus the otherwise seemingly extraneous "cookies" map
   753 	// The key of this map is a pointer to the corresponding &fCookie.cookie
   753 	// The key of this map is a pointer to the corresponding fCookie
   754 	cookies map[*interface{}]*fileObjCookie
   754 	cookies map[*fileObjCookie]struct{}
   755 }
   755 }
   756 
   756 
   757 // PortEvent is an abstraction of the port_event C struct.
   757 // PortEvent is an abstraction of the port_event C struct.
   758 // Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
   758 // Compare Source against PORT_SOURCE_FILE or PORT_SOURCE_FD
   759 // to see if Path or Fd was the event source. The other will be
   759 // to see if Path or Fd was the event source. The other will be
   776 	}
   776 	}
   777 	e := &EventPort{
   777 	e := &EventPort{
   778 		port:    port,
   778 		port:    port,
   779 		fds:     make(map[uintptr]*fileObjCookie),
   779 		fds:     make(map[uintptr]*fileObjCookie),
   780 		paths:   make(map[string]*fileObjCookie),
   780 		paths:   make(map[string]*fileObjCookie),
   781 		cookies: make(map[*interface{}]*fileObjCookie),
   781 		cookies: make(map[*fileObjCookie]struct{}),
   782 	}
   782 	}
   783 	return e, nil
   783 	return e, nil
   784 }
   784 }
   785 
   785 
   786 //sys	port_create() (n int, err error)
   786 //sys	port_create() (n int, err error)
   797 	if err != nil {
   797 	if err != nil {
   798 		return err
   798 		return err
   799 	}
   799 	}
   800 	e.fds = nil
   800 	e.fds = nil
   801 	e.paths = nil
   801 	e.paths = nil
       
   802 	e.cookies = nil
   802 	return nil
   803 	return nil
   803 }
   804 }
   804 
   805 
   805 // PathIsWatched checks to see if path is associated with this EventPort.
   806 // PathIsWatched checks to see if path is associated with this EventPort.
   806 func (e *EventPort) PathIsWatched(path string) bool {
   807 func (e *EventPort) PathIsWatched(path string) bool {
   824 	e.mu.Lock()
   825 	e.mu.Lock()
   825 	defer e.mu.Unlock()
   826 	defer e.mu.Unlock()
   826 	if _, found := e.paths[path]; found {
   827 	if _, found := e.paths[path]; found {
   827 		return fmt.Errorf("%v is already associated with this Event Port", path)
   828 		return fmt.Errorf("%v is already associated with this Event Port", path)
   828 	}
   829 	}
   829 	fobj, err := createFileObj(path, stat)
   830 	fCookie, err := createFileObjCookie(path, stat, cookie)
   830 	if err != nil {
   831 	if err != nil {
   831 		return err
   832 		return err
   832 	}
   833 	}
   833 	fCookie := &fileObjCookie{fobj, cookie}
   834 	_, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fCookie.fobj)), events, (*byte)(unsafe.Pointer(fCookie)))
   834 	_, err = port_associate(e.port, PORT_SOURCE_FILE, uintptr(unsafe.Pointer(fobj)), events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
       
   835 	if err != nil {
   835 	if err != nil {
   836 		return err
   836 		return err
   837 	}
   837 	}
   838 	e.paths[path] = fCookie
   838 	e.paths[path] = fCookie
   839 	e.cookies[&fCookie.cookie] = fCookie
   839 	e.cookies[fCookie] = struct{}{}
   840 	return nil
   840 	return nil
   841 }
   841 }
   842 
   842 
   843 // DissociatePath wraps port_dissociate(3c) for a filesystem path.
   843 // DissociatePath wraps port_dissociate(3c) for a filesystem path.
   844 func (e *EventPort) DissociatePath(path string) error {
   844 func (e *EventPort) DissociatePath(path string) error {
   856 		return err
   856 		return err
   857 	}
   857 	}
   858 	if err == nil {
   858 	if err == nil {
   859 		// dissociate was successful, safe to delete the cookie
   859 		// dissociate was successful, safe to delete the cookie
   860 		fCookie := e.paths[path]
   860 		fCookie := e.paths[path]
   861 		delete(e.cookies, &fCookie.cookie)
   861 		delete(e.cookies, fCookie)
   862 	}
   862 	}
   863 	delete(e.paths, path)
   863 	delete(e.paths, path)
   864 	return err
   864 	return err
   865 }
   865 }
   866 
   866 
   869 	e.mu.Lock()
   869 	e.mu.Lock()
   870 	defer e.mu.Unlock()
   870 	defer e.mu.Unlock()
   871 	if _, found := e.fds[fd]; found {
   871 	if _, found := e.fds[fd]; found {
   872 		return fmt.Errorf("%v is already associated with this Event Port", fd)
   872 		return fmt.Errorf("%v is already associated with this Event Port", fd)
   873 	}
   873 	}
   874 	fCookie := &fileObjCookie{nil, cookie}
   874 	fCookie, err := createFileObjCookie("", nil, cookie)
   875 	_, err := port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(&fCookie.cookie)))
       
   876 	if err != nil {
   875 	if err != nil {
   877 		return err
   876 		return err
   878 	}
   877 	}
       
   878 	_, err = port_associate(e.port, PORT_SOURCE_FD, fd, events, (*byte)(unsafe.Pointer(fCookie)))
       
   879 	if err != nil {
       
   880 		return err
       
   881 	}
   879 	e.fds[fd] = fCookie
   882 	e.fds[fd] = fCookie
   880 	e.cookies[&fCookie.cookie] = fCookie
   883 	e.cookies[fCookie] = struct{}{}
   881 	return nil
   884 	return nil
   882 }
   885 }
   883 
   886 
   884 // DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
   887 // DissociateFd wraps calls to port_dissociate(3c) on file descriptors.
   885 func (e *EventPort) DissociateFd(fd uintptr) error {
   888 func (e *EventPort) DissociateFd(fd uintptr) error {
   894 		return err
   897 		return err
   895 	}
   898 	}
   896 	if err == nil {
   899 	if err == nil {
   897 		// dissociate was successful, safe to delete the cookie
   900 		// dissociate was successful, safe to delete the cookie
   898 		fCookie := e.fds[fd]
   901 		fCookie := e.fds[fd]
   899 		delete(e.cookies, &fCookie.cookie)
   902 		delete(e.cookies, fCookie)
   900 	}
   903 	}
   901 	delete(e.fds, fd)
   904 	delete(e.fds, fd)
   902 	return err
   905 	return err
   903 }
   906 }
   904 
   907 
   905 func createFileObj(name string, stat os.FileInfo) (*fileObj, error) {
   908 func createFileObjCookie(name string, stat os.FileInfo, cookie interface{}) (*fileObjCookie, error) {
   906 	fobj := new(fileObj)
   909 	fCookie := new(fileObjCookie)
   907 	bs, err := ByteSliceFromString(name)
   910 	fCookie.cookie = cookie
   908 	if err != nil {
   911 	if name != "" && stat != nil {
   909 		return nil, err
   912 		fCookie.fobj = new(fileObj)
   910 	}
   913 		bs, err := ByteSliceFromString(name)
   911 	fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
   914 		if err != nil {
   912 	s := stat.Sys().(*syscall.Stat_t)
   915 			return nil, err
   913 	fobj.Atim.Sec = s.Atim.Sec
   916 		}
   914 	fobj.Atim.Nsec = s.Atim.Nsec
   917 		fCookie.fobj.Name = (*int8)(unsafe.Pointer(&bs[0]))
   915 	fobj.Mtim.Sec = s.Mtim.Sec
   918 		s := stat.Sys().(*syscall.Stat_t)
   916 	fobj.Mtim.Nsec = s.Mtim.Nsec
   919 		fCookie.fobj.Atim.Sec = s.Atim.Sec
   917 	fobj.Ctim.Sec = s.Ctim.Sec
   920 		fCookie.fobj.Atim.Nsec = s.Atim.Nsec
   918 	fobj.Ctim.Nsec = s.Ctim.Nsec
   921 		fCookie.fobj.Mtim.Sec = s.Mtim.Sec
   919 	return fobj, nil
   922 		fCookie.fobj.Mtim.Nsec = s.Mtim.Nsec
       
   923 		fCookie.fobj.Ctim.Sec = s.Ctim.Sec
       
   924 		fCookie.fobj.Ctim.Nsec = s.Ctim.Nsec
       
   925 	}
       
   926 	return fCookie, nil
   920 }
   927 }
   921 
   928 
   922 // GetOne wraps port_get(3c) and returns a single PortEvent.
   929 // GetOne wraps port_get(3c) and returns a single PortEvent.
   923 func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
   930 func (e *EventPort) GetOne(t *Timespec) (*PortEvent, error) {
   924 	pe := new(portEvent)
   931 	pe := new(portEvent)
   927 		return nil, err
   934 		return nil, err
   928 	}
   935 	}
   929 	p := new(PortEvent)
   936 	p := new(PortEvent)
   930 	e.mu.Lock()
   937 	e.mu.Lock()
   931 	defer e.mu.Unlock()
   938 	defer e.mu.Unlock()
   932 	e.peIntToExt(pe, p)
   939 	err = e.peIntToExt(pe, p)
       
   940 	if err != nil {
       
   941 		return nil, err
       
   942 	}
   933 	return p, nil
   943 	return p, nil
   934 }
   944 }
   935 
   945 
   936 // peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
   946 // peIntToExt converts a cgo portEvent struct into the friendlier PortEvent
   937 // NOTE: Always call this function while holding the e.mu mutex
   947 // NOTE: Always call this function while holding the e.mu mutex
   938 func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) {
   948 func (e *EventPort) peIntToExt(peInt *portEvent, peExt *PortEvent) error {
       
   949 	if e.cookies == nil {
       
   950 		return fmt.Errorf("this EventPort is already closed")
       
   951 	}
   939 	peExt.Events = peInt.Events
   952 	peExt.Events = peInt.Events
   940 	peExt.Source = peInt.Source
   953 	peExt.Source = peInt.Source
   941 	cookie := (*interface{})(unsafe.Pointer(peInt.User))
   954 	fCookie := (*fileObjCookie)(unsafe.Pointer(peInt.User))
   942 	peExt.Cookie = *cookie
   955 	_, found := e.cookies[fCookie]
       
   956 
       
   957 	if !found {
       
   958 		panic("unexpected event port address; may be due to kernel bug; see https://go.dev/issue/54254")
       
   959 	}
       
   960 	peExt.Cookie = fCookie.cookie
       
   961 	delete(e.cookies, fCookie)
       
   962 
   943 	switch peInt.Source {
   963 	switch peInt.Source {
   944 	case PORT_SOURCE_FD:
   964 	case PORT_SOURCE_FD:
   945 		delete(e.cookies, cookie)
       
   946 		peExt.Fd = uintptr(peInt.Object)
   965 		peExt.Fd = uintptr(peInt.Object)
   947 		// Only remove the fds entry if it exists and this cookie matches
   966 		// Only remove the fds entry if it exists and this cookie matches
   948 		if fobj, ok := e.fds[peExt.Fd]; ok {
   967 		if fobj, ok := e.fds[peExt.Fd]; ok {
   949 			if &fobj.cookie == cookie {
   968 			if fobj == fCookie {
   950 				delete(e.fds, peExt.Fd)
   969 				delete(e.fds, peExt.Fd)
   951 			}
   970 			}
   952 		}
   971 		}
   953 	case PORT_SOURCE_FILE:
   972 	case PORT_SOURCE_FILE:
   954 		if fCookie, ok := e.cookies[cookie]; ok && uintptr(unsafe.Pointer(fCookie.fobj)) == uintptr(peInt.Object) {
   973 		peExt.fobj = fCookie.fobj
   955 			// Use our stashed reference rather than using unsafe on what we got back
       
   956 			// the unsafe version would be (*fileObj)(unsafe.Pointer(uintptr(peInt.Object)))
       
   957 			peExt.fobj = fCookie.fobj
       
   958 		} else {
       
   959 			panic("mismanaged memory")
       
   960 		}
       
   961 		delete(e.cookies, cookie)
       
   962 		peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
   974 		peExt.Path = BytePtrToString((*byte)(unsafe.Pointer(peExt.fobj.Name)))
   963 		// Only remove the paths entry if it exists and this cookie matches
   975 		// Only remove the paths entry if it exists and this cookie matches
   964 		if fobj, ok := e.paths[peExt.Path]; ok {
   976 		if fobj, ok := e.paths[peExt.Path]; ok {
   965 			if &fobj.cookie == cookie {
   977 			if fobj == fCookie {
   966 				delete(e.paths, peExt.Path)
   978 				delete(e.paths, peExt.Path)
   967 			}
   979 			}
   968 		}
   980 		}
   969 	}
   981 	}
       
   982 	return nil
   970 }
   983 }
   971 
   984 
   972 // Pending wraps port_getn(3c) and returns how many events are pending.
   985 // Pending wraps port_getn(3c) and returns how many events are pending.
   973 func (e *EventPort) Pending() (int, error) {
   986 func (e *EventPort) Pending() (int, error) {
   974 	var n uint32 = 0
   987 	var n uint32 = 0
   988 		return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
  1001 		return 0, fmt.Errorf("len(s) (%d) is less than min events requested (%d)", len(s), min)
   989 	}
  1002 	}
   990 	got := uint32(min)
  1003 	got := uint32(min)
   991 	max := uint32(len(s))
  1004 	max := uint32(len(s))
   992 	var err error
  1005 	var err error
   993 	ps := make([]portEvent, max, max)
  1006 	ps := make([]portEvent, max)
   994 	_, err = port_getn(e.port, &ps[0], max, &got, timeout)
  1007 	_, err = port_getn(e.port, &ps[0], max, &got, timeout)
   995 	// got will be trustworthy with ETIME, but not any other error.
  1008 	// got will be trustworthy with ETIME, but not any other error.
   996 	if err != nil && err != ETIME {
  1009 	if err != nil && err != ETIME {
   997 		return 0, err
  1010 		return 0, err
   998 	}
  1011 	}
   999 	e.mu.Lock()
  1012 	e.mu.Lock()
  1000 	defer e.mu.Unlock()
  1013 	defer e.mu.Unlock()
       
  1014 	valid := 0
  1001 	for i := 0; i < int(got); i++ {
  1015 	for i := 0; i < int(got); i++ {
  1002 		e.peIntToExt(&ps[i], &s[i])
  1016 		err2 := e.peIntToExt(&ps[i], &s[i])
  1003 	}
  1017 		if err2 != nil {
  1004 	return int(got), err
  1018 			if valid == 0 && err == nil {
  1005 }
  1019 				// If err2 is the only error and there are no valid events
       
  1020 				// to return, return it to the caller.
       
  1021 				err = err2
       
  1022 			}
       
  1023 			break
       
  1024 		}
       
  1025 		valid = i + 1
       
  1026 	}
       
  1027 	return valid, err
       
  1028 }