Live data from Hacker News

Rust means never having to close a socket

blog.skylight.io

131–140 of 165 posts

Re: Rust means never having to close a socket

#131
post #122

Earlier quoted context omitted.

> You can write safe code that crashes in rust. That absolutely violates the safety guarantee whatever the reason for it. You can write Ruby code that calls into unsafe C code and SEGVs. This is a bug in the C code you called. It should have exposed a safe interface. You can write Rust code that calls into clearly delineated unsafe code and SEGVs. This is a bug in the unsafe code you called. It should have exposed a…

I'm not arguing any of these points. I'm just saying there are these two misconceptions: - if you write safe rust code, your code can't segfault This isn't true if your code path contains any unsafe code. - Rust code can't segfault This isn't true at all . Sure, if it does segfault its a bug in the c code / unsafe code. You're absolutely correct. ...but bugs aren't deliberate. Obviously no one is going to deliberatel…

  > If you have to trust the library is bug free, you're 
  > really no better off than using C++ are you?
This is a pretty far-out argument. For any programming language and environment, unless every dependency of your program including the compiler and runtime can be proven correct via formal verification, you will be susceptible to bugs. That doesn't imply that all code in the world is topologically as unsafe as C++. I can segfault Python if I try hard enough, and that's a bug in Python. Likewise I can segfault safe Rust code if I try hard enough, and that's a bug in Rust. I don't believe that anyone is really of the misconception that the mere use of Rust absolves you from the bugs of others, because that same person would have to believe that Rust somehow makes all bugs impossible, including bugs in C code that Rust calls into.

So let me give everyone a source to cite on Wikipedia:

"Rust does not keep C code from segfaulting." ~ kibwen

Re: Rust means never having to close a socket

#132

As someone who's been using (and really liking) rust for about 6 months, there are two things in this article which are, I'd say, 'common misconceptions' about rust: One of the coolest features of Rust is how it automatically manages resources for you, while still guaranteeing both safety (no segfaults) and high performance. In rust there are two types of code. 'safe' and 'unsafe'. The above is only true if your enti…

> That is, if you write entirely 100% safe code, and use some library that uses 'unsafe' code at a low level (this is very common; for example, an C binding or memory optimization), then rust does NOT guarantee safety.

What do you consider a "guarantee"? Do you consider pure JavaScript to "guarantee" safety, even though there have been exploitable bugs in the JIT and interpreter? Do you consider pure-computation, non-allocating Rust to be safe, even though LLVM may contain codegen bugs that allow for undefined behavior? Do you consider seccomp-isolated code to be safe, even though there have been, and will likely be in the future, kernel bugs that allow sandboxed process to escape?

The point is that instead of talking about "100% safe", which is never the case in the real world, I think it's better to talk about trusted computing bases. That is, instead of saying "X is safe" or "X is unsafe", we talk about what effect X has on the memory-unsafe surface area of a program. Rust's goal is to reduce the trusted computing base of an application written in it to the hardware, compiler, unsafe blocks, and type system. This gives us essentially the safety properties of "managed languages" (except I don't like that term because it tends to imply garbage collection and lack of fine-grained control over memory, which don't apply to Rust).

A specific example I like to give: Sure, we could hardwire (for instance) Vec into the language, and therefore reduce the number of lines of unsafe code in the libraries. But doing so would just be moving the unsafe code from the unsafe blocks in the libraries to the compiler itself. There would be no net gain in safety from it—compiler code can have bugs just as library code can—and there would be a decrease in maintainability and flexibility.

You can think of Rust's safety properties as establishing a type of sandbox if you'd like. All sandboxes have trusted computing bases, and Rust's compile-time sandbox is no exception. But "safety" as applied to a sandbox still has an important meaning. Chromium/Firefox OS's sandbox, for example, is a safe sandbox, even though its security depends on strong assumptions about the trustworthiness of the OS kernel and the IPC layer between the trusted and untrusted processes.

> There is a runtime cost to the drop checker; it's not particularly large, but it's certainly not just a sequence of drop operations.

After the drop optimizations are done, this will only be true if you conditionally move an object on one or more branches. It's already true today if the object gets SROA'd on the stack, as LLVM can then optimize out the drop flags. We've talked about adding a lint so the compiler can optionally warn and allow you to fix it if this performance cost is a concern to you. (It's a very minor cost—one test and branch on a stack byte, and again only if the object is conditionally moved.)

Note that C++ move semantics incurs essentially the same cost.

Re: Rust means never having to close a socket

#133

Earlier quoted context omitted.

> There is nothing undefined about using a unique_ptr after moving unless you use the internal pointer in undefined ways. If you dereference (i.e. use) a moved unique pointer you get undefined behavior. When talking about "using a pointer" most people mean dereferencing it, not for example comparing against null. It may be somewhat imprecise language, but it's what security people mean when they talk about "use after…

This is definitely outside the scope of my knowledge, but if you dereference a null pointer, won't you get an illegal memory access? Undefined behavior, at least colloquially, is about dereferencing a pointer to memory that may or may not be accessed and may or may not work/crash-the-program. That's what makes it undefined and an absolute disaster to track down. I'm pretty sure that if you try to deference memory add…

Dereferencing null is not guaranteed to do any particular behaviour; on many systems, getting the machine to actually dereference 0 will give a segfault/illegal memory access, but the compiler optimises assuming this never happens, and so can break a program that accidentally "relies" on it.

e.g.

- http://stackoverflow.com/q/6793262/1256624

- http://blog.llvm.org/2011/05/what-every-c-programmer-should-...

Re: Rust means never having to close a socket

#134
post #130

Earlier quoted context omitted.

I'm not arguing any of these points. I'm just saying there are these two misconceptions: - if you write safe rust code, your code can't segfault This isn't true if your code path contains any unsafe code. - Rust code can't segfault This isn't true at all . Sure, if it does segfault its a bug in the c code / unsafe code. You're absolutely correct. ...but bugs aren't deliberate. Obviously no one is going to deliberatel…

> The misconception is that if you're using rust you're safe from the bugs that other programmers may have made... which is not true. Of course it's not true, but the libraries you're using will (hopefully, for the most part) be written in Rust, which increases the level of trust. > There's a trust chain involved; if you depend on a library you trust it's bug free and won't delete your harddisk and crash your program…

> It is nonsense to say that "libraries can have bugs so you might as well use C++".

My argument is that if you assert 'rust is 100% safe' then you must assert, all your dependencies are bug free.

If you can somehow magically assert 'all my code is bug free', that would be great... but if so, you wouldn't need the borrow checker at all would you?

(I'm certainly not endorsing using C++ :P I'm specifically talking to the assertion that rust code can be safe, as per the definition of safety in the guide, that certain operations are impossible; certainly, and absolutely, rust code is safer and more trust worthy (imo) than c/c++ code... but you've got to be reasonable about what you're arguing. 'rust is magical and can never crash' turns up in blog posts a lot)

Re: Rust means never having to close a socket

#135
post #24
post #8

Earlier quoted context omitted.

> Wherever you would have written "socket.close()", in rust you can just say "drop(socket)". The difference is, it takes advantage of the ownership system to statically prove that you won't try to use the socket after close. Does a drop somehow say something to the type system as well, disallowing reads and writes afterwards? I'm new to rust, sorry if that's a stupid question.

In fact, the `drop` function is totally trivial. It's just a function that takes ownership of a thing, then does nothing with it whatsoever. In other words, the function body is entirely empty! :) https://github.com/rust-lang/rust/blob/master/src/libcore/me...

That's just too perfect. Of all things, your comment has raised my opinion of Rust the most.

Re: Rust means never having to close a socket

#136
post #88

Earlier quoted context omitted.

Everything in this article already works (and has for quite some time). The author is using it in production.

Yes, I know it is working for quite some time, I was more wondering if there are some hidden inherent problems lurking below the surface or if the theory behind rust is sound, e.g. some corner cases where it breaks down or result in undefined behaviour.

There's not yet any formal model that proves that the borrow checker is sound, but such work is forthcoming.

Re: Rust means never having to close a socket

#137
I love Rust, but really can't use it at work until it has a fully-featured AWS API. I had similar issues trying to use D and Dart in the past. Go doesn't have an official SDK either and although goamz isn't complete, the situation there is much better.

Re: Rust means never having to close a socket

#138
post #37
post #30

Earlier quoted context omitted.

Curious to know why `drop` isn't called automatically by the compiler as soon as possible (since the type system already seems to know it is safe). Is there a trade-off involved here?

Freeing resources as soon as humanly (computerly?) possible will optimize your memory usage, but can actually be worse for execution speed. If you're willing to use slightly more memory, it's generally faster to free memory in coarse chunks than one-thing-at-a-time. So even though Rust can conceivably free memory sooner, it might as well defer freeing until the end of the scope, since it can prove that that's safe. T…

Thanks. I can see the pro in that choice. But the con would be memory starvation (assuming that heap is bounded as in the JVM).

I think one middle-path could be to mark the resource as released as soon as compiler detects it, and then release it

1. when the allocator is starved or

2. when the resource goes out of scope

3. when drop() is explicitly called

Re: Rust means never having to close a socket

#139
post #136

Earlier quoted context omitted.

Yes, I know it is working for quite some time, I was more wondering if there are some hidden inherent problems lurking below the surface or if the theory behind rust is sound, e.g. some corner cases where it breaks down or result in undefined behaviour.

There's not yet any formal model that proves that the borrow checker is sound, but such work is forthcoming.

https://github.com/nikomatsakis/rust-redex

Re: Rust means never having to close a socket

#140
post #129

Earlier quoted context omitted.

> If you use `nokogiri` in Ruby and get a segfault, that is a bug in nokogiri. It is not an indication that Ruby is unsafe. Rust has a strict definition of safety; not all rust code for fills that guarantee. We're not talking fast and loose here. These are absolute definitions. You can write safe code that crashes in rust. That absolutely violates the safety guarantee whatever the reason for it. > This is in the proc…

> No it's not. > What's happening is some of the run time overhead is being reduced. I believe wycats was responding specifically to > Rust uses 'drop flags', which are extra bytes at the end of struct instances in memroy , to track objects and keep meta information about them to determine if they should be dropped. And these are being eliminated. That is the drop flag will be entirely separate to the struct instance…

Whatever, there are still drop flags (on the stack instead, sure), and still dynamic runtime checks for drops.

The points I was making is that 'zero cost' memory management isn't 100% zero cost. The drop checker does incur some basic dynamic runtime costs.

To be 'zero cost' drop behaviour would be determined at compile time.

Post reply on HN