haskell / process

Library for dealing with system processes
http://hackage.haskell.org/package/process
Other
87 stars 82 forks source link

Decreasing process priority... #281

Open mgajda opened 1 year ago

mgajda commented 1 year ago

The way that process attributes are handled on Posix platforms is that we call a function just after fork and before exec. This allows common actions like:

Most of these use cases are already supported by CreateProcess interface, however decreasing priority, and dropping capabilities is not supported.

I suggest adding new fields to CreateProcess:

  1. lowerCPUPriority :: Int -- lower priority of the child process
  2. ioPriority :: Int -- lower IO priority (see https://linux.die.net/man/1/ionice)
  3. dropCapabilities :: [Capability] -- drop process capabilities (see https://hackage.haskell.org/package/linux-capabilities-0.1.1.0/docs/System-Linux-Capabilities.html for a list of capabilities, and https://man7.org/linux/man-pages/man7/capabilities.7.html for explanations)
  4. changeNamespace :: NamespaceChange (see https://en.wikipedia.org/wiki/Linux_namespaces) With additional datatype:

    data NamespaceChange = SameNamespace
                         | CloneNamespace [Unshare]
                         | EnterNamespace FD
    

Use cases for 1 and 2 are particularly common when managing batch jobs from user interface. Facilitation would help all interactive applications, in particular language server.

Facilitating 3 and 4 would encourage using Haskell for high-security applications, since both capabilties and namespaces are used for secure containers.

I am willing to provide MR, if maintainers accept. The numbers above indicate both simplicity and frequency with which new features are likely to be used.

snoyberg commented 1 year ago

@bgamari any thoughts on this? I lean towards saying this makes sense, but you're more familiar with the POSIX APIs than I am.

bgamari commented 1 year ago

The way that process attributes are handled on Posix platforms is that we call a function just after fork and before exec.

The problem is that this isn't strictly true at this point. At least one widely used UNIX-like platform (Darwin) has been strongly pushing users against using fork/exec and towards posix_spawn. Sadly, posix_spawn isn't nearly as flexible as fork/exec.

This puts us in a tricky position: do we want process to be a flexible library which exposes the full capabilities of the underlying platform, or do we want it to be a platform-independent abstraction over least-common-denominator process operations? Currently it seems to endeavor to be a bit of both so honestly I'm not sure how to answer this.

geekosaur commented 1 year ago

I think we're stuck with the portability interface because even if we stick to POSIX we still need to deal with e.g. FreeBSD, which doesn't use the same capability and namespace abstractions as Linux. And of course Darwin which does its own thing, as usual.

That said, the problem with separating this out is that it just defers the problem; System.Posix.Process still needs to deal with them, and pretty much pushes the whole "so how do you do this safely and correctly?" question that the wrapper at least tries to address onto the end programmer.

I'm tempted to suggest making the current System.Process the least common denominator, and System.Posix.Process export a vaguely similar API but with an extensibility interface instead of either wiring Linuxisms into it or trying to support the intersection of all supported "Posix" OSes.

geekosaur commented 1 year ago

On second thought, we already have multiple POSIXisms and multiple Windowsisms in CreateProcess, so it's already a zoo and we should be thinking about ways to fix it anyway.