summaryrefslogtreecommitdiff
path: root/_posts/2017-09-28-perl6-creating-a-background-service.adoc
diff options
context:
space:
mode:
Diffstat (limited to '_posts/2017-09-28-perl6-creating-a-background-service.adoc')
-rw-r--r--_posts/2017-09-28-perl6-creating-a-background-service.adoc159
1 files changed, 0 insertions, 159 deletions
diff --git a/_posts/2017-09-28-perl6-creating-a-background-service.adoc b/_posts/2017-09-28-perl6-creating-a-background-service.adoc
deleted file mode 100644
index 4cc759d..0000000
--- a/_posts/2017-09-28-perl6-creating-a-background-service.adoc
+++ /dev/null
@@ -1,159 +0,0 @@
----
-date: 2017-09-28 15:11:43
-tags: Tutorial Perl6 Programming Raku
-description: >
- I've recently made some progress on Shinrin, a centralized logging system in
- Perl 6. This has to run as service, which means that for most service
- managers it has to be able to run in the background.
----
-= Perl 6 - Creating a background service
-:toc: preamble
-
-I've recently made some progress on
-https://github.com/scriptkitties/perl6-Shinrin[Shinrin], a centralized logging
-system in Perl 6. This has to run as service, which means that for most service
-managers it has to be able to run in the background.
-
-[NOTE]
-====
-If you just want to get to the solution and don't care for the details, just
-head straight to link:#the-final-solution[the full script].
-====
-
-== It's not possible!
-After a lot of trying and talking with the folks at
-irc://chat.freenode.net:6697/#perl6[#perl6] I was told that it is not possible
-to do this in pure Perl 6, explained by people with more knowledge than I have
-on the internals:
-
-[quote, jnthn]
-____
-(jnthn suspects fork + multi-threaded VM = pain) Since fork only clones one
-thread - the one that called it. So suddenly you've got an instance of the VM
-missing most of its threads.
-____
-
-[quote, geekosaur]
-____
-The most common failure mode is that some thread is holding e.g. a mutex (or a
-userspace lock) during the fork. The thread goes away but the lock is process
-level and remains, with nothing around to know to unlock it. So then things
-work until something else needs that lock and suddenly you deadlock.
-____
-
-Not much later, `jnthn` https://github.com/perl6/doc/commit/8f9443c3ac[pushed a
-commit] to update the docs to clarify that a `fork` call through `NativeCall`
-will probably not give the result you were hoping for.
-
-== Or is it?
-Luckily, the same people were able to think up of a work-around, which can be
-made in POSIX sh, so it's usable on any decent OS. The workaround is to let a
-little shell script fork into the background, and let that run the Perl
-application.
-
-=== A first example
-This is fairly simple to create, as in this example to launch `shinrind` in the
-background:
-
-[source,sh]
-----
-#! /usr/bin/env sh
-
-main()
-{
- perl6 -Ilib bin/shinrind "$@"
-}
-
-main "$@" &
-----
-
-This works just fine if the working directory is correct. This means you need
-to be in the parent directory to `lib` and `bin` of the program to make it
-work.
-
-== Improving the forking script
-While that short script works fine to show a proof of concept, in order to make
-it viable for real-world scenarios, it can use some improvements. After all, it
-would be annoying if you'd have to `cd` to a specific directory any time you
-want to start your application.
-
-=== Ensure you are in the directory you should be in
-So for starters, let's make sure that you can run it from anywhere on your
-system. For this, you should set the working directory for the script, so you
-don't have to do it manually. Because the script runs in its own subshell, the
-shell you're working from remains unaffected.
-
-A POSIX compliant way to get the directory the script is stored in is as
-follows:
-
-[source,sh]
-----
-DIR=$(CDPATH="" cd -- "$(dirname -- "$0")" && pwd)
-----
-
-This will set `$DIR` to the path of the directory the shell script is stored
-in. You can simply `cd` to that and be assured you're in the right directory.
-
-In Perl 6, it is expected for executable files to live in the `bin` directory
-of your project repository. So you should actually be in the parent of the
-directory holding your script. Furthermore, you should check the `cd` command
-executed correctly, just to be safe.
-
-[source,sh]
-----
-cd -- "${DIR}/.." || exit
-----
-
-=== Disable `STDOUT` and `STDERR`
-A started service should not be polluting your interactive shell, so you should
-disable (or otherwise redirect) `STDOUT` and `STDERR`. This is done in the
-shell using a small bit of code behind whatever you want to redirect:
-
-[source,sh]
-----
-> /dev/null 2>&1
-----
-
-This will set `STDOUT` to `/dev/null`, and set `STDERR` to the same stream as
-`STDOUT`, which in effect will make all output go to `/dev/null`. If you want
-to log everything to a single file, you can replace `/dev/null` with another
-file of your choice. If you don't want logs to be overwritten on each start,
-use a `>>` instead of a single `>` at the start.
-
-If you want to log errors and output in different files, you can use the
-following:
-
-[source,sh]
-----
-> /var/log/service.log 2> /var/log/service.err
-----
-
-This will put standard output in `/var/log/service.log` and errors in
-`/var/log/service.err`.
-
-=== Fork just the Perl 6 program
-In the initial example, I put the `&` behind the `main` call, at the bottom of
-the script. While this works just fine for most simple usage, if you want to do
-additional chores, like creating a pidfile after starting the Perl 6 program,
-you're out of luck. If you were to only fork the Perl 6 application, you could
-handle some other cases in the shell script.
-
-== The final solution
-For those eager to just get going with this, here is the complete example
-script to just fork your Perl program into the background:
-
-[source,sh]
-----
-#! /usr/bin/env sh
-
-readonly DIR=$(CDPATH="" cd -- "$(dirname -- "$0")" && pwd)
-
-main()
-{
- cd -- "${DIR}/.." || exit
-
- perl6 -Ilib bin/shinrind "$@" > /dev/null >2&1 &
-}
-
-main "$@"
-----