mirror of
git://git.yoctoproject.org/poky.git
synced 2025-07-19 12:59:02 +02:00

This adds the SPDX-License-Identifier license headers to the majority of our source files to make it clearer exactly which license files are under. The bulk of the files are under GPL v2.0 with one found to be under V2.0 or later, some under MIT and some have dual license. There are some files which are potentially harder to classify where we've imported upstream code and those can be handled specifically in later commits. The COPYING file is replaced with LICENSE.X files which contain the full license texts. (Bitbake rev: ff237c33337f4da2ca06c3a2c49699bc26608a6b) Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
98 lines
3.7 KiB
Python
98 lines
3.7 KiB
Python
#
|
|
# SPDX-License-Identifier: GPL-2.0-only
|
|
#
|
|
|
|
"""
|
|
Python Daemonizing helper
|
|
|
|
Originally based on code Copyright (C) 2005 Chad J. Schroeder but now heavily modified
|
|
to allow a function to be daemonized and return for bitbake use by Richard Purdie
|
|
"""
|
|
|
|
import os
|
|
import sys
|
|
import io
|
|
import traceback
|
|
|
|
def createDaemon(function, logfile):
|
|
"""
|
|
Detach a process from the controlling terminal and run it in the
|
|
background as a daemon, returning control to the caller.
|
|
"""
|
|
|
|
# Ensure stdout/stderror are flushed before forking to avoid duplicate output
|
|
sys.stdout.flush()
|
|
sys.stderr.flush()
|
|
|
|
try:
|
|
# Fork a child process so the parent can exit. This returns control to
|
|
# the command-line or shell. It also guarantees that the child will not
|
|
# be a process group leader, since the child receives a new process ID
|
|
# and inherits the parent's process group ID. This step is required
|
|
# to insure that the next call to os.setsid is successful.
|
|
pid = os.fork()
|
|
except OSError as e:
|
|
raise Exception("%s [%d]" % (e.strerror, e.errno))
|
|
|
|
if (pid == 0): # The first child.
|
|
# To become the session leader of this new session and the process group
|
|
# leader of the new process group, we call os.setsid(). The process is
|
|
# also guaranteed not to have a controlling terminal.
|
|
os.setsid()
|
|
try:
|
|
# 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.
|
|
pid = os.fork() # Fork a second child.
|
|
except OSError as e:
|
|
raise Exception("%s [%d]" % (e.strerror, e.errno))
|
|
|
|
if (pid != 0):
|
|
# Parent (the first child) of the second child.
|
|
# exit() or _exit()?
|
|
# _exit is like exit(), but it doesn't call any functions registered
|
|
# with atexit (and on_exit) or any registered signal handlers. It also
|
|
# closes any open file descriptors, but doesn't flush any buffered output.
|
|
# Using exit() may cause all any temporary files to be unexpectedly
|
|
# removed. It's therefore recommended that child branches of a fork()
|
|
# and the parent branch(es) of a daemon use _exit().
|
|
os._exit(0)
|
|
else:
|
|
os.waitpid(pid, 0)
|
|
return
|
|
|
|
# The second child.
|
|
|
|
# Replace standard fds with our own
|
|
with open('/dev/null', 'r') as si:
|
|
os.dup2(si.fileno(), sys.stdin.fileno())
|
|
|
|
try:
|
|
so = open(logfile, 'a+')
|
|
os.dup2(so.fileno(), sys.stdout.fileno())
|
|
os.dup2(so.fileno(), sys.stderr.fileno())
|
|
except io.UnsupportedOperation:
|
|
sys.stdout = open(logfile, 'a+')
|
|
|
|
# Have stdout and stderr be the same so log output matches chronologically
|
|
# and there aren't two seperate buffers
|
|
sys.stderr = sys.stdout
|
|
|
|
try:
|
|
function()
|
|
except Exception as e:
|
|
traceback.print_exc()
|
|
finally:
|
|
bb.event.print_ui_queue()
|
|
# os._exit() doesn't flush open files like os.exit() does. Manually flush
|
|
# stdout and stderr so that any logging output will be seen, particularly
|
|
# exception tracebacks.
|
|
sys.stdout.flush()
|
|
sys.stderr.flush()
|
|
os._exit(0)
|