A synchronous, single-threaded interface for starting processes on Linux

Related tags

Miscellaneoussfork
Overview

Summary

sfork is a prototype for a new system call on Linux which provides a synchronous, single-threaded interface for starting processes.

sfork can be viewed as a variation on vfork which does the minimal amount of work required to make vfork actually useful and usable. In particular, sfork removes all the traditional restrictions vfork has on what you can do in the child process.

Interface

The raw interface is identical to the usual prototypes on Linux for vfork, exit, and execveat:

int sfork();
int sfork_exit(int status);
int sfork_execveat(int dirfd, const char* pathname, char *const argv[],
                   char *const envp[], int flags);

However, unlike traditional fork and vfork, sfork only ever returns once. sfork always returns 0 on success, or a negative value if forking failed for any of the usual reasons, like a cap on the number of processes.

The pid, then, is obtained from the return value of exit or execveat. Of course, those system calls don’t usually return, hence the need to wrap them with sfork-supporting equivalents.

In other words, the control flow for sfork is different from the control flow for fork and vfork.

Control flow for fork and vfork proceeds as below. Each line is numbered according to the order in which it is reached. (Error checking is omitted for simplicity)

int ret; // 1
printf("I'm in the parent"); // 2
ret = vfork();  // 3 and 7
if (ret == 0) { // 4 and 8
  printf("I'm in the child"); // 5
  exec(); // 6
} else {
  printf("I'm in the parent once again"); // 9
  printf("Pid of child is %d", ret); // 10
}

Control flow for sfork proceeds like this (again, with error checking omitted):

int ret; // 1
printf("I'm in the parent"); // 2
sfork();  // 3
printf("I'm in the child"); // 4
ret = exec(); // 5
printf("I'm in the parent once again"); // 6
printf("Pid of child is %d", ret); // 7

Control flow works like that naturally in any language that calls sfork, like any other normal function call.

For example, with the Python wrapper, exceptions thrown in the child automatically propagate up. The subprocess() contextmanager in the Python wrapper catches exceptions, automatically calls exit(1) to exit the child process context and re-enter the parent process context, and rethrows the exception. So if a user application encounters an error while setting up the child, the error is naturally and easily propagated up.

A clean way to understand sfork, is to view it as moving a single existing thread of control from an existing process context, the parent, to a new, fresh process context, the child, which starts off sharing its address space with the parent.

In this view, after a call to sfork, exec is an overloaded operation which does three things: Creates a new address space inside the current process context and loads the executable into it, creates a new thread starting at the executable entry point in the current process context and the new address space, and returns the current thread to the parent process context.

And exit, after a call to sfork, just destroys the current process context (setting the exit code), and returns the current thread to the parent process context.

In this view, sfork actually is much more like unshare than fork or vfork. Like unshare, sfork creates a new execution context and moves the current thread into that execution context. Unfortunately, sfork cannot currently be implemented with unshare; see the discussion in appropriate section below.

Userspace implementation

Recall that vfork shares the memory space between the parent process and child process, and blocks the thread in the parent process that executes vfork. The thread in the parent process is unblocked when the child process calls either exec or exit.

The kernel, when implementing vfork, saves the parent process’s registers and restores them after the parent is resumed. To achieve the behavior of sfork, we would rather the kernel just not save and restore the registers at all, but rather, just continue control flow from the point of the child process’s exec.

If you view vfork as just moving a single thread of control between processes, then the fact that the kernel saves the registers of this thread at the point of calling vfork, and then restores them when calling exec or exit, becomes obviously unnecessary: Merely not doing that save and restore gives us sfork. Without that save and restore, we get a single continuous control flow without any jumps.

So all that the sfork wrapper does is perform the exact opposite jump of the kernel: It saves the child process’s registers at the point of exec or exit, and restore those child registers immediately after the parent process is resumed with the parent’s saved registers. This register save/restore exactly counteracts the kernel’s register save/restore.

Possible implementation using unshare

Instead of calling vfork to create a new process context, sfork could call unshare(CLONE_SIGHAND|CLONE_FILES|CLONE_FS) to create a new process context and move the current thread into it.

Then, instead of calling exec, we would call clone(new_stack, CLONE_VM) while inside the new process context, with an appropriately set up new_stack to immediately call exec.

Then to return to the parent process context, we would call setns(procfd, CLONE_SIGHAND|CLONE_FILES|CLONE_FS), where procfd is a file descriptor pointing to the parent process context.

The main missing piece here is that there’s no way to get a file descriptor representing the parent process context, and setns does not support passing any of CLONE_SIGHAND|CLONE_FILES|CLONE_FS, so there’s no way for the thread to return to the parent process.

Also, unshare doesn’t allow calling CLONE_SIGHAND in multi-threaded applications, for good reason. Properly dealing with signals will be tricky.

Also, unshare doesn’t allow calling CLONE_VM in multi-threaded applications, for reasons which are unclear to me. I think that could be changed to be allowed.

Also, calling clone(new_stack, CLONE_VM) will copy the address space, negating one of the main advantages of a vfork style approach. We may need some other specialized system call that runs an executable in a new address space on a new thread, inheriting all the parts of the execution context.

Owner
Spencer Baugh
Spencer Baugh
A python script that fetches the grades of a student from a WAEC result in pdf format.

About waec-result-analyzer A python script that fetches the grades of a student from a WAEC result in pdf format. Built for federal government college

Oshodi Kolapo 2 Dec 04, 2021
Albert launcher extension for rolling dice.

dice-roll-albert-ext Extension for rolling dice in Albert launcher Installation Locate the modules directory in the Python extension data directory. T

Jonah Lawrence 1 Nov 18, 2021
A small program to vote for Councilors at 42 Heilbronn.

This Docker container is build to run on server an provide an easy to use interface for every student to vote for their councillors. To run docker on

Kevin Hirsig 2 Jan 17, 2022
Module 2's katas from Launch X's python introduction course.

Module2Katas Module 2's katas from Launch X's python introduction course. Virtual environment creation process (on Windows): Create a folder in any de

Javier Méndez 1 Feb 10, 2022
program to store and update pokemons using SQL and Flask

Pokemon SQL and Flask Pokemons api in python. Technologies flask pymysql Description PokeCorp is a company that tracks pokemon and their trainers arou

Sara Hindy Salfer 1 Oct 20, 2021
Grammar of Scalable Linked Interactive Nucleotide Graphics

Gosling.js Gosling.js is a declarative grammar for interactive (epi)genomics visualization on the Web. ⚠️ Please be aware that the grammar of Gosling.

Gosling 126 Nov 29, 2022
🎅🏻 Helping santa understand ✨ python ✨

☃️ Advent of code 2021 ☃️ Helping santa understand ✨ python ✨

Fluffy 2 Dec 25, 2021
A simple python project that can find Tangkeke in a given image.

A simple python project that can find Tangkeke in a given image. Make the real Tangkeke image as a kernel to convolute the target image. The area wher

张志衡 1 Dec 08, 2021
this is a basic python project that I made using python

this is a basic python project that I made using python. This project is only for practice because my python skills are still newbie.

Elvira Firmansyah 2 Dec 14, 2022
Cross-Encoder-with-Bi-Encoder를 활용한 WebPage 데모

Retrieval_Streamlit_Demo Cross-Encoder-with-Bi-Encoder를 활용한

5 Dec 29, 2021
This is an online course where you can learn and master the skill of low-level performance analysis and tuning.

Performance Ninja Class This is an online course where you can learn to find and fix low-level performance issues, for example CPU cache misses and br

Denis Bakhvalov 1.2k Dec 30, 2022
Easy way to build a SaaS application using Python and Dash

EasySaaS This project will be attempt to make a great starting point for your next big business as easy and efficent as possible. This project will cr

xianhu 3 Nov 17, 2022
Collection of script & resources for Foundry's Nuke software.

Author: Liam Collod. Collections of scripting stuff I wrote for Foundry's Nuke software. Utilisation You can have a look at the README.md file in each

Liam Collod 1 May 14, 2022
A python package that adds "docs" command to disnake

About This extension's purpose is of adding a "docs" command, its purpose is to help documenting in chat. How To Load It from disnake.ext import comma

7 Jan 03, 2023
Interpreting-compiling programming language.

HoneyASM The programming language written on Python, which can be as interpreted as compiled. HoneyASM is easy for use very optimized PL, which can so

TalismanChet 1 Dec 25, 2021
Do you need a screensaver for CircuitPython? Of course you do

circuitpython_screensaver Do you need a screensaver for CircuitPython? Of course you do Demo video of dvdlogo screensaver: screensaver_dvdlogo.mp4 Dem

Tod E. Kurt 8 Sep 02, 2021
Reload all Blender add-on modules

Reload-Addon This add-on creates a list of the modules that the add-on selected in the drop-down menu contains and reloads them with the keyboard shor

2 Dec 02, 2021
A Python feed reader library.

reader is a Python feed reader library. It aims to allow writing feed reader applications without any business code, and without enforcing a dependenc

266 Dec 30, 2022
KeyBrowser: A program launches a browser and a keylogger at the same time, is used to retrieve a person's personal information

KeyBrowser: A program launches a browser and a keylogger at the same time, is used to retrieve a person's personal information

3 Oct 16, 2022
You will need to install a few python packages for this one.

Features Bait support Auto repair will repair every 10 catches Anti detection (still a work in progress) but using random times and click positions Pr

12 Sep 21, 2022