Documentation
¶
Overview ¶
Package launchd provides pure go bindings for macOS launchd.
Supports launch_activate_socket without using cgo.
Index ¶
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func Files ¶
Files returns slice of *os.File backed by file descriptors for given socket.
- syscall.EALREADY is returned if socket is already activated.
- syscall.ENOENT or syscall.ESRCH is returned if socket is not found.
- syscall.ESRCH is returned if calling process is not manged by launchd.
- syscall.EINVAL is returned if socket name is invalid.
- syscall.ENOTSUP is returned on non-macOS platforms (including iOS).
This must be called exactly once for given socket name. Subsequent calls with the same socket name will return syscall.EALREADY.
func Listeners ¶
Listeners returns slice of net.Listener for specified TCP/stream socket.
In case of error building listeners, an appropriate error is returned, along with a partial list of listeners. It is the responsibility of the caller to close the returned non-nil listeners whenever required.
Closing returned listeners does not close underlying file descriptor and closing files does not affect the listeners.
- syscall.EALREADY is returned if socket is already activated.
- syscall.ENOENT or syscall.ESRCH is returned if socket is not found.
- syscall.ESOCKTNOSUPPORT is returned if socket is of incorrect type.
- syscall.ESRCH is returned if calling process is not manged by launchd.
- syscall.EINVAL is returned if socket name is invalid.
- syscall.ENOTSUP is returned on non macOS platforms (including iOS).
This must be called exactly once for a given socket name. Subsequent calls with the same socket name will return syscall.EALREADY.
Example ¶
// SPDX-FileCopyrightText: Copyright 2023 Prasad Tengse
// SPDX-License-Identifier: MIT
package main
import (
"context"
"errors"
"log/slog"
"net"
"net/http"
"os"
"os/signal"
"sync"
"syscall"
"time"
"github.com/tprasadtp/go-launchd"
)
// WaitGroup to wait on multiple listeners.
var wg sync.WaitGroup
func main() {
// This example only works on macOS, But is shown on all platforms
// for ease of use. This cannot be used for systemd socket activation.
listeners, err := launchd.Listeners("socket-name-as-in-plist")
if err != nil {
slog.Error("Error getting socket activated listeners", "err", err)
// Handle error and close any active listeners.
for _, item := range listeners {
item.Close()
}
os.Exit(1)
}
// A simple HTTP handler. Replace this with your actual implementation.
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
_, _ = w.Write([]byte("Hello From Socket Activated Server\n"))
slog.Info("Request received",
"client", r.RemoteAddr,
"method", r.Method,
"url", r.URL)
})
// Make servers stoppable with ctrl+x or SIGTERM.
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
// Because there may be multiple listeners, we need to have as many servers as listeners.
servers := make([]*http.Server, 0, len(listeners))
for range listeners {
servers = append(servers, &http.Server{
Handler: handler,
ReadHeaderTimeout: time.Second * 30,
})
}
for i := range listeners {
// Wait for context to cancel and stop server.
wg.Add(1)
go func(s *http.Server, l net.Listener) {
defer wg.Done()
var err error
for {
select {
case <-ctx.Done():
slog.Info("Stopping server", "address", l.Addr())
// In production do this with a timeout.
err = s.Shutdown(context.Background())
if err != nil && !errors.Is(err, http.ErrServerClosed) {
slog.Error("Failed to shutdown server",
"err", err, "address", l.Addr())
}
return
}
}
}(servers[i], listeners[i])
// Run servers in background if context is not already cancelled.
if ctx.Err() == nil {
wg.Add(1)
go func(s *http.Server, l net.Listener) {
defer wg.Done()
slog.Info("Starting server", "address", l.Addr())
if err := s.Serve(l); !errors.Is(err, http.ErrServerClosed) {
slog.Error("Error", "address", l.Addr(), "err", err)
cancel()
}
}(servers[i], listeners[i])
}
}
// Wait for all servers to exit.
wg.Wait()
slog.Info("Server(s) stopped")
}
Output:
func PacketListeners ¶
func PacketListeners(name string) ([]net.PacketConn, error)
PacketListeners returns slice of net.PacketConn for specified UDP/datagram socket.
In case of error building net.PacketConn, an appropriate error is returned, along with a partial list of net.PacketConn. It is the responsibility of the caller to close the returned non-nil listeners whenever required.
Closing returned listeners does not close underlying file descriptor and closing files does not affect the listeners.
- syscall.EALREADY is returned if socket is already activated.
- syscall.ENOENT or syscall.ESRCH is returned if socket is not found.
- syscall.ESOCKTNOSUPPORT is returned if socket is of incorrect type.
- syscall.ESRCH is returned if calling process is not manged by launchd.
- syscall.EINVAL is returned if socket name is invalid.
- syscall.ENOTSUP is returned on non macOS platforms (including iOS).
This must be called exactly once for a given socket name. Subsequent calls with the same socket name will return syscall.EALREADY.
func UDPListeners
deprecated
func UDPListeners(name string) ([]net.PacketConn, error)
Deprecated: Use PacketListeners.
Types ¶
This section is empty.