Subject: [shepherd] chdir and invoke do not work as intended in services
From: Maxim Cournoyer <[email-masked]>
To: bug-guix <[email-masked]>
Date: Thu, 10 Apr 2025 23:44:04 +0900
List-Id: <debbugs-submit.debbugs.gnu.org>

Hi,

It appears that when changing directory and calling a program with
'invoke', the program still has its current working directory set to
'/'.

I'm betting this may be some kind of odd interaction between the
Shepherd service threads and forking a process?

Can we improve that?  If it's a limitation of the implementation model,
than I think it's a surprising enough gotcha to warrant documenting it
in Shepherd's manual.

Here's a simple reproducer:

--8<---------------cut here---------------start------------->8---
modified   gnu/system/examples/bare-bones.tmpl
@@ -3,8 +3,8 @@
 ;; for a "bare bones" setup, with no X11 display server.
 
 (use-modules (gnu))
-(use-service-modules networking ssh)
-(use-package-modules screen ssh)
+(use-service-modules networking shepherd ssh)
+(use-package-modules base screen ssh)
 
 (operating-system
   (host-name "komputilo")
@@ -47,7 +47,20 @@
 
   ;; Add services to the baseline: a DHCP client and an SSH
   ;; server.  You may wish to add an NTP service here.
-  (services (append (list (service dhcp-client-service-type)
+  (services (append (list (simple-service
+                           'forked-processes-cwd-wrong
+                           shepherd-root-service-type
+                           (list
+                            (shepherd-service
+                             (provision '(bug-77115))
+                             (start #~(lambda _
+                                        (mkdir "/etc/testdir")
+                                        (chdir "/etc/testdir")
+                                        (invoke #$(file-append coreutils "/bin/touch")
+                                                "new-file.txt")
+                                        #t))
+                             (one-shot? #t))))
+                          (service dhcp-client-service-type)
                           (service openssh-service-type
                                    (openssh-configuration
                                     (openssh openssh-sans-x)
--8<---------------cut here---------------end--------------->8---

Then run it from your tree using something like:

--8<---------------cut here---------------start------------->8---
$(./pre-inst-env guix system vm gnu/system/examples/bare-bones.tmpl --no-graphic)
--8<---------------cut here---------------end--------------->8---

You should see upon inspection that:

--8<---------------cut here---------------start------------->8---
root@komputilo ~# ls /new-file.txt 
/new-file.txt                        # wrong place
root@komputilo ~# ls /etc/testdir/   # empty
--8<---------------cut here---------------end--------------->8---

-- 
Thanks,
Maxim