Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Android/build/build/soong/ui/build/paths/   (Android Betriebssystem Version 17©)  Datei vom 26.5.2026 mit Größe 4 kB image not shown  

Quelle  logs.go   Sprache: unbekannt

 
Spracherkennung für: .go vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

// Copyright 2018 Google Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package paths

import (
 "context"
 "encoding/gob"
 "fmt"
 "io/ioutil"
 "net"
 "os"
 "path/filepath"
 "runtime"
 "sync"
 "syscall"
 "time"
)

type LogProcess struct {
 Pid     int
 Command string
}

type LogEntry struct {
 Basename string
 Args     []string
 Parents  []LogProcess
}

const timeoutDuration = time.Duration(100) * time.Millisecond

type socketAddrFunc func(string) (string, func(), error)

func procFallback(name string) (string, func(), error) {
 d, err := os.Open(filepath.Dir(name))
 if err != nil {
  return "", func() {}, err
 }

 return fmt.Sprintf("/proc/self/fd/%d/%s", d.Fd(), filepath.Base(name)), func() {
  d.Close()
 }, nil
}

func tmpFallback(name string) (addr string, cleanup func(), err error) {
 d, err := ioutil.TempDir("/tmp", "log_sock")
 if err != nil {
  cleanup = func() {}
  return
 }
 cleanup = func() {
  os.RemoveAll(d)
 }

 dir := filepath.Dir(name)

 absDir, err := filepath.Abs(dir)
 if err != nil {
  return
 }

 err = os.Symlink(absDir, filepath.Join(d, "d"))
 if err != nil {
  return
 }

 addr = filepath.Join(d, "d", filepath.Base(name))

 return
}

func getSocketAddr(name string) (string, func(), error) {
 maxNameLen := len(syscall.RawSockaddrUnix{}.Path)

 if len(name) < maxNameLen {
  return name, func() {}, nil
 }

 if runtime.GOOS == "linux" {
  addr, cleanup, err := procFallback(name)
  if err == nil {
   if len(addr) < maxNameLen {
    return addr, cleanup, nil
   }
  }
  cleanup()
 }

 addr, cleanup, err := tmpFallback(name)
 if err == nil {
  if len(addr) < maxNameLen {
   return addr, cleanup, nil
  }
 }
 cleanup()

 return name, func() {}, fmt.Errorf("Path to socket is still over size limit, fallbacks failed.")
}

func dial(name string, lookup socketAddrFunc, timeout time.Duration) (net.Conn, error) {
 socket, cleanup, err := lookup(name)
 defer cleanup()
 if err != nil {
  return nil, err
 }

 dialer := &net.Dialer{
  Timeout: timeout,
 }
 return dialer.Dial("unix", socket)
}

func listen(name string, lookup socketAddrFunc) (net.Listener, error) {
 socket, cleanup, err := lookup(name)
 defer cleanup()
 if err != nil {
  return nil, err
 }

 return net.Listen("unix", socket)
}

func SendLog(logSocket string, entry *LogEntry, done chan interface{}) {
 sendLog(logSocket, getSocketAddr, timeoutDuration, entry, done)
}

func sendLog(logSocket string, lookup socketAddrFunc, timeout time.Duration, entry *LogEntry, done chan interface{}) {
 defer close(done)

 conn, err := dial(logSocket, lookup, timeout)
 if err != nil {
  return
 }
 defer conn.Close()

 if timeout != 0 {
  conn.SetDeadline(time.Now().Add(timeout))
 }

 enc := gob.NewEncoder(conn)
 enc.Encode(entry)
}

func LogListener(ctx context.Context, logSocket string) (chan *LogEntry, error) {
 return logListener(ctx, logSocket, getSocketAddr)
}

func logListener(ctx context.Context, logSocket string, lookup socketAddrFunc) (chan *LogEntry, error) {
 ret := make(chan *LogEntry, 5)

 if err := os.Remove(logSocket); err != nil && !os.IsNotExist(err) {
  return nil, err
 }

 ln, err := listen(logSocket, lookup)
 if err != nil {
  return nil, err
 }

 go func() {
  for {
   select {
   case <-ctx.Done():
    ln.Close()
   }
  }
 }()

 go func() {
  var wg sync.WaitGroup
  defer func() {
   wg.Wait()
   close(ret)
  }()

  for {
   conn, err := ln.Accept()
   if err != nil {
    ln.Close()
    break
   }
   conn.SetDeadline(time.Now().Add(timeoutDuration))
   wg.Add(1)

   go func() {
    defer wg.Done()
    defer conn.Close()

    dec := gob.NewDecoder(conn)
    entry := &LogEntry{}
    if err := dec.Decode(entry); err != nil {
     return
    }
    ret <- entry
   }()
  }
 }()
 return ret, nil
}

[Dauer der Verarbeitung: 0.21 Sekunden, vorverarbeitet 2026-06-28]