@@ -1689,3 +1689,91 @@ func TestFreezer(t *testing.T) {
16891689
16901690 runStopUnit (t , conn , TrUnitProp {target , nil })
16911691}
1692+
1693+ func testAttachProcessesToUnit (t * testing.T , subcgroup string ) {
1694+ target := "attach-processes.service"
1695+ conn := setupConn (t )
1696+ defer conn .Close ()
1697+
1698+ setupUnit (target , conn , t )
1699+ linkUnit (target , conn , t )
1700+
1701+ // Start the unit first.
1702+ reschan := make (chan string )
1703+ _ , err := conn .StartUnit (target , "replace" , reschan )
1704+ if err != nil {
1705+ t .Fatal (err )
1706+ }
1707+ job := <- reschan
1708+ if job != "done" {
1709+ t .Fatal ("Job is not done:" , job )
1710+ }
1711+
1712+ // Cleanup.
1713+ defer func () {
1714+ _ , err = conn .StopUnit (target , "replace" , reschan )
1715+ if err != nil {
1716+ t .Fatal (err )
1717+ }
1718+ <- reschan
1719+ }()
1720+
1721+ if subcgroup != "" {
1722+ // Pre-create a sub-cgroup.
1723+ prop , err := conn .GetServiceProperty (target , "ControlGroup" )
1724+ if err != nil {
1725+ t .Fatal (err )
1726+ }
1727+ path := prop .Value .Value ().(string )
1728+ err = os .Mkdir (filepath .Join ("/sys/fs/cgroup" , path , subcgroup ), 0777 )
1729+ if err != nil {
1730+ t .Fatal (err )
1731+ }
1732+
1733+ }
1734+
1735+ // Start a test process that we can attach.
1736+ cmd := exec .Command ("/bin/sleep" , "400" )
1737+ err = cmd .Start ()
1738+ if err != nil {
1739+ t .Fatal (err )
1740+ }
1741+ defer func () {
1742+ cmd .Process .Kill ()
1743+ cmd .Wait ()
1744+ }()
1745+
1746+ pid := uint32 (cmd .Process .Pid )
1747+
1748+ // Test attaching the process to the unit.
1749+ ctx := context .Background ()
1750+ err = conn .AttachProcessesToUnit (ctx , target , subcgroup , []uint32 {pid })
1751+ if err != nil {
1752+ // AttachProcessesToUnit might not be supported on all systemd versions.
1753+ e , ok := err .(dbus.Error )
1754+ if ok && (e .Name == "org.freedesktop.DBus.Error.UnknownMethod" ||
1755+ e .Name == "org.freedesktop.DBus.Error.NotSupported" ) {
1756+ t .SkipNow ()
1757+ }
1758+ t .Fatalf ("failed to attach process %d to unit %s: %s" , pid , target , err )
1759+ }
1760+
1761+ // Verify the process was attached by getting the unit it belongs to.
1762+ attachedPath , err := conn .GetUnitByPID (ctx , pid )
1763+ if err != nil {
1764+ t .Fatal (err )
1765+ }
1766+
1767+ attachedUnit := unitName (attachedPath )
1768+ if attachedUnit != target {
1769+ t .Fatalf ("process was not attached to correct unit: got %s, want %s" , attachedUnit , target )
1770+ }
1771+ }
1772+
1773+ func TestAttachProcessesToUnit (t * testing.T ) {
1774+ testAttachProcessesToUnit (t , "" )
1775+ }
1776+
1777+ func TestAttachProcessesToUnitWithSubcgroup (t * testing.T ) {
1778+ testAttachProcessesToUnit (t , "/test-subcgroup" )
1779+ }
0 commit comments