Asked  7 Months ago    Answers:  5   Viewed   93 times

I'm trying to create a daemon in python. I've found the following question, which has some good resources in it which I am currently following, but I'm curious as to why a double fork is necessary. I've scratched around google and found plenty of resources declaring that one is necessary, but not why.

Some mention that it is to prevent the daemon from acquiring a controlling terminal. How would it do this without the second fork? What are the repercussions?

 Answers

41

Looking at the code referenced in the question, the justification is:

Fork a second child and exit immediately to prevent zombies. This causes the second child process to be orphaned, making the init process responsible for its cleanup. And, since the first child is a session leader without a controlling terminal, it's possible for it to acquire one by opening a terminal in the future (System V- based systems). This second fork guarantees that the child is no longer a session leader, preventing the daemon from ever acquiring a controlling terminal.

So it is to ensure that the daemon is re-parented onto init (just in case the process kicking off the daemon is long lived), and removes any chance of the daemon reacquiring a controlling tty. So if neither of these cases apply, then one fork should be sufficient. "Unix Network Programming - Stevens" has a good section on this.

Tuesday, June 1, 2021
 
keyBeatz
answered 7 Months ago
30

Some threads do background tasks, like sending keepalive packets, or performing periodic garbage collection, or whatever. These are only useful when the main program is running, and it's okay to kill them off once the other, non-daemon, threads have exited.

Without daemon threads, you'd have to keep track of them, and tell them to exit, before your program can completely quit. By setting them as daemon threads, you can let them run and forget about them, and when your program quits, any daemon threads are killed automatically.

Tuesday, June 1, 2021
 
Baba
answered 7 Months ago
10

Generally, there are two strategies to handle a situation like this:

1. Use Exclusive FKs

Essentially, each of the possible parent tables will have its own, separate foreign key in the child table, and there is a CHECK enforcing exactly one of them is non-NULL. Since FKs are only enforced on non-NULL fields, only one of the FKs will be enforced.

For example:

enter image description here

(relationship between user and group omitted)

CHECK (
    (group_id IS NOT NULL AND user_id IS NULL)
    OR (group_id IS NULL AND user_id IS NOT NULL)
)

2. Use Inheritance

Inherit user and group from a common supertype and then connect the setting to the supertype:

enter image description here

For more information on inheritance (aka. category, subclassing, subtype, generalization hierarchy etc.), take a look at "Subtype Relationships" chapter of ERwin Methods Guide. Unfortunately, modern DBMSes don't natively support inheritance - for some ideas about physically implementing it, take a look at this post.

This is a heavy-duty solution probably not justified for just two tables (groups and users), but can be quite "scalable" for many tables.

Sunday, June 6, 2021
 
Francisunoxx
answered 6 Months ago
27

If you specify thread.daemon = True for your python thread, then the program will halt immediately when only the daemon is left. The the commands sent to stdout are lost.

Add this to a file called main.py

import threading
import time

def int_sleep():
  for _ in range(1, 600):
    time.sleep(1)
    print("sleep")

def main():
  thread = threading.Thread(target=int_sleep)
  thread.daemon = True
  thread.start()
  time.sleep(2)
  print("main thread end...")

thread = threading.Thread(target=main)
thread.daemon = True
thread.start()

Run it like this:

el@apollo:~/code/python/run01$ python --version
Python 2.7.6
el@apollo:~$ python main.py 
el@apollo:~$

See it prints nothing because the thread started. You set it to be a daemon and started it. Then the program ended.

Extra notes: If you paste this code into a python interpreter, all the print statements will appear on the terminal because the daemon never loses hold of its connection to stdout.

Read more: http://docs.python.org/2/library/threading.html

Wednesday, August 4, 2021
 
Kzqai
answered 4 Months ago
36

If you say __PACKAGE__->run(@ARGV) then run can be defined in a class you inherit from or allows a class to inherit from this one. If you just say run(@ARGV) you are missing the class information. This only matters if you are doing OO style programming.

Put the following in a file named Foo.pm, and then say perl Foo.pm 1 2 3

package Foo;

use strict;
use warnings;

__PACKAGE__->main(@ARGV) unless caller;

sub main {
    my $class = shift;
    my $obj   = $class->new(@ARGV);
    print $obj->to_string, "n";
}

sub new {
    my $class = shift;
    return bless [@_], $class;
}

sub to_string {
    my $self = shift;
    return "args: " . join ", ", map { "[$_]" } @$self;
}

1;

Now put the following in Bar.pm, and say perl Bar.pm a b c.

package Bar;

use strict;
use warnings;

use base 'Foo';

__PACKAGE__->main(@ARGV) unless caller;

sub to_string {
    my $self = shift;
    return "args: " . join ", ", map { "<$_>" } @$self;
}

1;

Now lets see what happens if you don't use __PACKAGE__ in this environment. Make the first section of code in Foo.pm look like this:

main(@ARGV) unless caller;

sub main {
    my $obj = Foo->new(@ARGV);
    print $obj->to_string, "n";
}

Now run perl Foo.pm 1 2 3. Everything should still look right. Now try running perl Bar.pm a b c. We still get output, but it is not the output we expect. What happens if we remove __PACKAGE__ from Bar.pm? Well, we get and error: Undefined subroutine &Bar::main called at Bar.pm line 8. This is because there is no main function in the module and we are not calling it with the class, so it won't look for it in the Foo package anymore.

Saturday, August 14, 2021
 
Evernoob
answered 4 Months ago
Only authorized users can answer the question. Please sign in first, or register a free account.
Not the answer you're looking for? Browse other questions tagged :  
Share