From mboxrd@z Thu Jan 1 00:00:00 1970 From: Thorsten Wilms Subject: Re: XWayland, /tmp/.X11-unix Date: Thu, 29 Mar 2018 16:37:48 +0200 Message-ID: References: <87po3xava2.fsf@elephly.net> <87efk3s8um.fsf@gmail.com> Reply-To: t_w_@freenet.de Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit Return-path: Received: from eggs.gnu.org ([2001:4830:134:3::10]:55745) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1f1Yik-0007Jg-S4 for guix-devel@gnu.org; Thu, 29 Mar 2018 10:40:08 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1f1Yih-0003oR-MJ for guix-devel@gnu.org; Thu, 29 Mar 2018 10:40:06 -0400 Received: from mout0.freenet.de ([2001:748:100:40::2:2]:53832) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1f1Yih-0003lm-Bk for guix-devel@gnu.org; Thu, 29 Mar 2018 10:40:03 -0400 Received: from [195.4.92.140] (helo=mjail0.freenet.de) by mout0.freenet.de with esmtpa (ID t_w_@freenet.de) (port 25) (Exim 4.90_1 #2) id 1f1Yid-0005R3-ON for guix-devel@gnu.org; Thu, 29 Mar 2018 16:40:00 +0200 Received: from [::1] (port=42918 helo=mjail0.freenet.de) by mjail0.freenet.de with esmtpa (ID t_w_@freenet.de) (Exim 4.90_1 #2) id 1f1Yid-0003yl-KL for guix-devel@gnu.org; Thu, 29 Mar 2018 16:39:59 +0200 Received: from mx11.freenet.de ([195.4.92.21]:35542) by mjail0.freenet.de with esmtpa (ID t_w_@freenet.de) (Exim 4.90_1 #2) id 1f1YgZ-0002f9-8K for guix-devel@gnu.org; Thu, 29 Mar 2018 16:37:51 +0200 In-Reply-To: <87efk3s8um.fsf@gmail.com> Content-Language: en-GB List-Id: "Development of GNU Guix and the GNU System distribution." List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: guix-devel-bounces+gcggd-guix-devel=m.gmane.org@gnu.org Sender: "Guix-devel" Cc: Guix-devel Thank you, Chris, for taking the time to go into such detail! However, as mentioned later in the thread, I arrived at a solution days ago. It just took finding a close match among existing services and recalling some basics about Scheme evaluation :) Your write-up did improve my idea of what is going on, though I guess I may have to reread it later on, to get more out of it. On 29.03.2018 08:18, Chris Marusich wrote: > Thorsten Wilms writes: > >> On 22.03.2018 00:00, Ricardo Wurmus wrote: >>> >>> Thorsten Wilms writes: >>> >>>> Initially I thought creation of /tmp/.X11-unix should be tied to the >>>> xorg-server-xwayland package, but since it is more generic: which >>>> component should create that dir on Guix SD (based on what)? >>> >>> It is needed at run-time (because packages cannot create files outside >>> of their store prefix at build time), so it should be created by a >>> system service. A service is not the same as a shepherd service; we >>> also have activation services that run once and only create a file or a >>> directory. >> >> After 2 to 3 hours of research, going through documentation and >> various .scm, I still don't even manage to write a service for my >> system configuration that just does a (mkdir-p "/tmp/.X11-uni"), so >> figuring out how to make that dependent on the actual need is way >> outside my capabilities. > > Take heart: it is not easy for me, either. :-) > >> Should I file a bug, and if so, against what? > > If this is a problem that is preventing you from building something new, > then discussing it here is probably the right approach. If it's > affecting an existing package or service in Guix, then you might want to > create a bug for it by emailing bug-guix@gnu.org. > > By the way, to create a "service" that does what you need, you might > find it useful to look at an existing example service. For example, the > procedure nscd-activation in gnu/services/base.scm does something > similar. So does the procedure exim-activation in > gnu/services/mail.scm. > > The manual does explain what is going on (see: (guix) Service > Reference), but I have read it multiple times and examined the source > multiple times, and I still have trouble remembering exactly how it all > fits together. > > I'll try to explain how I understand it. In Guix, a service is a > object; sometimes this is also referred to as a service > "instance". A object contains two other objects: a "type" and > a "value". The "type" is a object and is sometimes > referred to as the service "kind" (because it represents what kind of > service it is). The "value" is whatever that particular service type > requires, and sometimes it is also referred to as a service's > "parameter", "parameters", or "parameter value". Usually the value is a > configuration object of some kind. For example, the Guix service > expects its value to be a object. > > By the way, these objects with angle brackets, like , are > defined using the define-record-type* syntax (which itself is defined in > guix/records.scm). They are similar to normal Scheme records (see: > (guile) Record Overview), if you're familiar with those. > > Guix has an "activation service". Its purpose, as described in the > manual (see: (guix) Service Types and Services), is to run a code > snippet "at activation time - e.g., when the service is booted". The > basic contract for extending the "activation service" is that if you > define an extension of the activation service which specifies a > "compute" procedure foo, where foo is a procedure that returns a > G-Expression that takes some action (e.g., create the "/tmp/.X11-uni" > directory), then that action will be taken at activation time. The > "foo" procedure will receive a single argument as input: the argument > will be the value of the service (your service!) that is extending the > activation service. > > Confused? I know I was when I first looked into this. But stay with me > - together we can make it through! The mechanism that implements the > extension logic can be found in the fold-services procedure in > gnu/services.scm. Specifically, when a service like the Guix service > extends an extensible service like the activation service, we have the > following situation: > > * A guix-service-type is defined (in gnu/services/base.scm). It > contains a for which the "target" is the > activation-service-type and the "compute" is the guix-activation > procedure. > > * We add an instance of the Guix service to the %base-services list by > calling the guix-service procedure. This procedure creates an > instance of the service and uses %default-guix-configuration as its > value (which is a object). > > * The activation-service-type is defined (in gnu/services.scm). Its > "compose" is the append procedure (see: (guile) Append/Reverse), and > its "extend" is the second-argument procedure. > > * We add an instance of the activation service to the essential-services > list. The activation service's initial value is #t. > > When Guix builds all the system services, it will do the following: > > * Guix will find a service of the activation-service-type. This is the > activation service. > > * Guix will find a service of the guix-service-type. This is the Guix > service. > > * Guix will recognize that the Guix service extends the activation > service. > > * Guix will pass the Guix service's value to the guix-service-type's > "compute" procedure defined earlier. This means that Guix will call > the guix-activation procedure with a single argument: the > %default-guix-configuration. The guix-activation procedure returns an > appropriate G-Expression that takes steps to activate Guix according > to the provided configuration. > > * If there are any other services that extend the > activation-service-type, Guix will call their "compute" procedures in > a similar fashion. > > * Guix will collect all of the objects returned by the various "compute" > procedures in a list. The G-Expression returned by guix-activation > will be one element of this list. Guix will pass this list to the > activation-service-type's "compose" procedure. This means that it > will call append with a single argument: the list. This will actually > return the same list, since appending a single list returns the same > list. (As explained elsewhere on the guix-devel email list, this > should really be the "identity" procedure, not the "append" procedure, > since it more accurately reflects the intent [1].) > > * Guix will call the activation-service-type's "extend" procedure with > two arguments: the first argument is the value of the activation > service found earlier, and the second argument is the result of the > "compose" procedure from the previous step. This means that Guix will > call the second-argument procedure with the value #t as its first > argument, and the list of G-Expressions from above as its second > argument. Because the second-argument procedure simply returns the > second argument, the value #t will be ignored, and the result will be > the list of G-Expressions. > > * Guix replaces the activation service with a new service instance that > has the same type but a new value. The new value is set to the result > of calling the "extend" procedure. This means that the activation > service will be replaced with a new activation service that uses the > list of G-Expressions from the previous step as its value. > > Guix repeats this process recursively for all services defined in your > declaration. In this way, even though the high-level > contract for how services extend one another is dictated by Guix, the > interpretation of the objects and procedures involved is largely > determined by the service that is being extended. For example, Guix > promises the activation service that it will collect objects from > services that extend the activation service and then call the activation > service's "compose" and "extend" procedures as described above to create > a new, modified activation service. However, the structure of those > objects and the behavior of those procedures are largely determined by > the activation-service-type itself. A different type of service may > very well define a different contract. > > To re-iterate what I wrote earlier, the activation-service-type's > contract is as follows: when you define a service that extends it (i.e., > when you define a that extends the > activation-service-type), your service will define a "compute" procedure > that returns a G-Expression that performs some action (e.g., create a > directory). The activation service will then arrange to run that action > at activation time. This means that if your service needs a > "/tmp/.X11-uni" directory to exist before it runs, you need to define a > "compute" procedure that accepts a single argument (which will be your > service's value) and returns a G-Expression that creates the directory. > Different extensible services have different expectations, so you would > need to implement different "compute" procedures to extend them. > Thankfully, even if an extensible service is not clearly documented, you > can usually tell what its contract is by looking at some services that > extend it already. > > I hope that helps! > > Footnotes: > [1] https://lists.gnu.org/archive/html/guix-devel/2018-03/msg00307.html > -- Thorsten Wilms thorwil's design for free software: http://thorwil.wordpress.com/