Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add LibC.setrlimit/LibC.getrlimit to all linux/bsd platforms #10569

Open
wants to merge 11 commits into
base: master
Choose a base branch
from
21 changes: 21 additions & 0 deletions spec/std/system_spec.cr
Original file line number Diff line number Diff line change
Expand Up @@ -23,4 +23,25 @@ describe System do
cpu_count.should eq(shell_cpus)
end
end

describe "file_descriptor_limit" do
it "returns the current file descriptor limit" do
hard_fd_limit = `ulimit -Hn`.strip
$?.success?.should be_true
soft_fd_limit = `ulimit -Sn`.strip
$?.success?.should be_true

soft_limit, hard_limit = System.file_descriptor_limit
hard_limit.to_s.should eq hard_fd_limit
soft_limit.to_s.should eq soft_fd_limit
end

it "can set the limit" do
System.file_descriptor_limit = 512

soft_fd_limit = `ulimit -Sn`.strip
$?.success?.should be_true
soft_fd_limit.should eq "512"
end
end
end
1 change: 1 addition & 0 deletions src/crystal/system.cr
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ end

{% if flag?(:unix) %}
require "./system/unix/hostname"
require "./system/unix/file_descriptor_limit"

{% if flag?(:bsd) %}
require "./system/unix/sysctl_cpucount"
Expand Down
18 changes: 18 additions & 0 deletions src/crystal/system/unix/file_descriptor_limit.cr
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
module Crystal::System
def self.file_descriptor_limit
rlimit = uninitialized LibC::Rlimit
if LibC.getrlimit(LibC::RLIMIT_NOFILE, pointerof(rlimit)) != 0
raise RuntimeError.from_errno("Could not get rlimit")
end
{rlimit.rlim_cur, rlimit.rlim_max}
end

def self.file_descriptor_limit=(limit) : Nil
rlimit = LibC::Rlimit.new
rlimit.rlim_cur = limit
rlimit.rlim_max = limit
if LibC.setrlimit(LibC::RLIMIT_NOFILE, pointerof(rlimit)) != 0
raise RuntimeError.from_errno("Could not set rlimit")
end
end
end
4 changes: 3 additions & 1 deletion src/lib_c/aarch64-darwin/c/sys/resource.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ lib LibC
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_STACK = 3
RLIMIT_NOFILE = 7

struct RUsage
ru_utime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/aarch64-linux-gnu/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULongLong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 7

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/aarch64-linux-musl/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULongLong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 7

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/arm-linux-gnueabihf/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 7

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/i386-linux-gnu/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 7

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/i386-linux-musl/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 7

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
4 changes: 3 additions & 1 deletion src/lib_c/x86_64-darwin/c/sys/resource.cr
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@ lib LibC
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_STACK = 3
RLIMIT_NOFILE = 7

struct RUsage
ru_utime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/x86_64-dragonfly/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULongLong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 8

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/x86_64-freebsd/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULongLong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 8

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/x86_64-linux-gnu/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULongLong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 7

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/x86_64-linux-musl/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULongLong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 7

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/x86_64-netbsd/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULongLong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 8

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
13 changes: 13 additions & 0 deletions src/lib_c/x86_64-openbsd/c/sys/resource.cr
Original file line number Diff line number Diff line change
@@ -1,4 +1,17 @@
lib LibC
alias RlimT = ULongLong

struct Rlimit
rlim_cur : RlimT
rlim_max : RlimT
end

fun getrlimit(Int, Rlimit*) : Int
fun setrlimit(Int, Rlimit*) : Int

RLIMIT_STACK = 3
RLIMIT_NOFILE = 8

struct RUsage
ru_utime : Timeval
ru_stime : Timeval
Expand Down
18 changes: 18 additions & 0 deletions src/system.cr
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,22 @@ module System
def self.cpu_count
Crystal::System.cpu_count
end

# Returns the soft and hard file descriptor limits for the current process
#
# ```
# System.file_descriptor_limit # => { 1024, 524288 }
# ```
def self.file_descriptor_limit
Crystal::System.file_descriptor_limit
end

# Sets the soft file descriptor limits for the current process
#
# ```
# System.file_descriptor_limit = 4096
# ```
def self.file_descriptor_limit=(limit)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If this is an int, can we add a type restriction?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
def self.file_descriptor_limit=(limit)
def self.file_descriptor_limit=(limit : UInt32)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

UInt32 technically doesn't cut it the value is 64 bits wide on 64-bit platforms. In practice, this shouldn't be relevant, though. So we can perhaps stay with 32 bits. But maybe it should be signed instead? We try to avoid unsigned integer types in stdlib APIs.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In any case, the same type should be applied as return type of the getter method.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was thinking just Int

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the param type restriction, that would be good. But what about the return type?

Crystal::System.file_descriptor_limit = limit
end
end