talos/internal/app/init/shutdown.go
Andrey Smirnov 3dc5606053 fix(init): don't close ACPI listen handle too early (#647)
Signed-off-by: Andrey Smirnov <smirnov.andrey@gmail.com>
2019-05-13 07:50:21 -07:00

70 lines
1.4 KiB
Go

/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package main
import (
"log"
"github.com/mdlayher/genetlink"
"github.com/mdlayher/netlink"
"github.com/pkg/errors"
)
const (
// See https://github.com/torvalds/linux/blob/master/drivers/acpi/event.c
acpiGenlFamilyName = "acpi_event"
acpiGenlMcastGroupName = "acpi_mc_group"
)
func listenForPowerButton() (poweroffCh <-chan struct{}, err error) {
// Get the acpi_event family.
conn, err := genetlink.Dial(nil)
if err != nil {
return nil, err
}
f, err := conn.GetFamily(acpiGenlFamilyName)
if netlink.IsNotExist(err) {
// nolint: errcheck
conn.Close()
return nil, errors.Wrap(err, acpiGenlFamilyName+" not available")
}
var id uint32
for _, group := range f.Groups {
if group.Name == acpiGenlMcastGroupName {
id = group.ID
}
}
if err = conn.JoinGroup(id); err != nil {
// nolint: errcheck
conn.Close()
return nil, err
}
// Listen for ACPI events.
ch := make(chan struct{})
go func() {
// nolint: errcheck
defer conn.Close()
for {
msgs, _, err := conn.Receive()
if err != nil {
log.Printf("error reading from ACPI channel: %s", err)
return
}
if len(msgs) > 0 {
close(ch)
return
}
}
}()
return ch, nil
}