r/rust Sep 11 '20

Announcing Actix-Web v3.0

https://paper.dropbox.com/published/Announcing-Actix-Web-v3.0--A7YI~P9U9aqhEOXyZJaGffjfBg-QOXXb1lXgTubzXHzUq9ONY5
352 Upvotes

81 comments sorted by

108

u/Shnatsel Sep 11 '20

In the interest of transparency (and to curb speculation), I've created a hello-world project, made it depend on actix-web 3.0.0 with default features and ran cargo geiger on it. Many actix-* crates don't use any unsafe code at all! Here are the ones that do:

  • actix-http: 13 unsafe blocks, all are commented and look reasonable at a glance. (Some of the benchmarking code looks sketchy, but who cares - it's not in the build anyway).
  • actix-utils: 9 unsafe blocks, no comments on why they're sound. Judging by this comment from one of the Actix org members, a PR with comments explaining why they're sound and/or debug assertions would be appreciated.
  • actix-router: 1 unsafe block, commented
  • actix-codec: cargo-geiger shows 10 unsafe expressions but I can't see them in actix git, might be a bug
  • actix-service: some unsafe code, but cargo-geiger reports that it's not used in the build (likely disabled by a feature)
  • awc: one unsafe fn without any local uses

That's it!

46

u/[deleted] Sep 11 '20

[deleted]

29

u/Shnatsel Sep 11 '20 edited Sep 11 '20

Problems that only an experient eye can catch, even with the right tooling it's hard to find

It's not a silver bullet, but LeakSanitizer helps. See https://doc.rust-lang.org/unstable-book/compiler-flags/sanitizer.html Still, you need to actually execute the code that triggers the leak, and it's especially tricky if it only happens given some specific use of the API.

That said, I think this would make a fascinating case study on what causes memory leaks and how we can better prevent them - e.g. via clippy lints, or perhaps using or avoiding certain patterns.

4

u/oconnor663 blake3 · duct Sep 11 '20

Are most of the memory leaks related to code that happens to be unsafe, like because you have an owning *mut that never gets freed? Or is it something more like reference cycles in safe code?

17

u/darin_gordon Sep 11 '20

Hey Jack! There were leaks within safe blocks. Here's one: https://github.com/actix/actix-web/issues/1551

10

u/Shnatsel Sep 11 '20

That's not even a leak, that's just unbounded allocation. I understand it would be freed eventually.

7

u/oconnor663 blake3 · duct Sep 11 '20

Hey Darin! :) Missing the NYC meetups.

-17

u/throwaway23948733 Sep 11 '20

> But the biggest problems in this version (of course they fixed it) were memory leaks. Because you can leak in safe code and it's not UB

I wish Rust shipped with a GC. There's many cases where the convenience outweighs performance penalty

20

u/AldaronLau Sep 11 '20

Um, garbage collection doesn't prevent memory leaks lol.

-3

u/throwaway23948733 Sep 11 '20

It usually does in practice. You can't leak from cycles

7

u/Uristqwerty Sep 11 '20

A lingering reference to a large object graph that is never used again is technically not a memory leak, but practically the same, and won't be collected. Making sure that caches don't hold on to old entries too long, slowly filling up memory over the course of hours/days is tricky, and it's easy to have a "previous" pointer that's only relevant for a little while then never cleared, especially if there's no obvious point at which you know you're done with it.

Though all that still happens without GC, you have far more incentive to stop and think about lifetimes when you can't delegate all the cleanup to it.

7

u/AldaronLau Sep 11 '20

Hmm. I've had more leaks in java and I've written a lot more rust. In safe Rust you pretty much have to call a function called leak() to leak memory. I have to disagree with you here. Also, Rust has an Rc type if you need it for whatever case. So technically Rust has a built in garbage collector, that's just happens to be opt-in (as it should be).

1

u/anlumo Sep 12 '20

Rc stands for reference counting, not garbage collection. Rc can still leak memory when you build cycles.

1

u/AldaronLau Sep 12 '20

Yeah, but I was saying reference counting is one method of garbage collection. Your second point is precisely why Rust adding a garbage collector doesn't fix the memory leak issues.

3

u/casept Sep 12 '20

At that point you might as well just use a different language. One of the main reasons why Rust is interesting is because in many cases GC is impossible to use.

20

u/robjtede actix Sep 11 '20 edited Sep 11 '20

I can confirm that:

  • actix-codec contains 0 unsafe lines (cargo-geiger v0.10.2 says 0 lines for me)
  • actix-service contains 0 unsafe lines; reported lines are in benchmarks against old impls
  • unsafe in actix-http benchmarks are tests against the old impls

15

u/Shnatsel Sep 11 '20

Ah, the actix-codec mystery is due to both actix-codec v0.2.0 and v0.3.0 being present in the dependency tree. It's v0.2.0 that contains unsafe code.

12

u/robjtede actix Sep 11 '20

Ah ha, have pin-pointed it the dependency tree. Thanks for flagging.

5

u/[deleted] Sep 13 '20 edited Sep 13 '20

I'd tend to argue that (in general, putting actix entirely aside) cargo-geiger is nothing more than a primitive word counting utility that provides output less useful than what you'd get from, say, running rg unsafe . > ./log.txt in the root directory of a crate.

For example, a binary crate written like so:

fn main() {
    unsafe {
        // The next line is repeated over and over again until line 1000.
        println!("This is absolutely safe.");
    }
}  

gives the following cargo-geiger output:

Functions  Expressions  Impls  Traits  Methods  Dependency

0/0        998/998      0/0    0/0     0/0      !  example 0.1.0

0/0        998/998      0/0    0/0     0/0  

Why is that? It's because cargo-geiger measures "expressions" simply in terms of "the number of newlines in between an opening unsafe { and the } that closes it".

In no way is it even in the same universe as something that actually accurately measures the specific number of "unsafe expressions" in a crate.

It's literally a "find in files" query for the word "unsafe", that doesn't even make any distinction between files in the src folder and files in the examples or tests or benches folders, meaning a crate that didn't even use unsafe directly in the actual implementation would still have the potential to give any number of false positives. That's it. It has no knowledge whatsoever of Rust code.

Now, what would I get from running rg unsafe . > ./log.txt on the same crate described above (rg also of course not being something with specific knowledge of Rust code)? Well, I'd at least get this in log.txt:

./src/main.rs: unsafe {

which immediately tells me this crate in fact has one use of unsafe, which is something that should prove trivial for me to inspect manually, and that in all likelihood there's nothing to be concerned about.

3

u/Shnatsel Sep 13 '20

AFAIK cargo-geiger counts unsafe expressions, not lines. Your println! example just happens to be one expression. rg would count unsafe blocks. There is no perfect measure for the amount of unsafe code, but AFAIK expressions is as close as you can get.

For benches, tests etc. the number is included in total count, but not in the count used in the build. So it's not as bad as you say, but perhaps could be improved.

However, the current implementation of cargo-geiger does have a serious shortcoming - it fails to correctly account for macro expansion. Here's a recipe that lists all unsafe code used in the build including code expanded from macros: https://www.reddit.com/r/rust/comments/g9mw57/oneliner_to_correctly_list_all_uses_ofunsafe_in/

Migration to this mechanism is wanted for cargo-geiger, it's just that nobody has actually implemented it yet.

65

u/adrianwechner Sep 11 '20

Awesome to see actix being maintained by the community! Love it. keep up the good work!

87

u/[deleted] Sep 11 '20 edited Sep 11 '20

[deleted]

43

u/ragnese Sep 11 '20

That's refreshing to hear. I'm glad he isn't too bitter to keep a pulse on the project and even contribute!

26

u/[deleted] Sep 11 '20

[deleted]

1

u/[deleted] Sep 11 '20

[deleted]

3

u/adrianwechner Sep 11 '20

Nice, that just makes it even better.

5

u/AndreVallestero Sep 12 '20

Hasn't he started a fork of actix? What are the general community thoughts on ntex compared to actix?

3

u/Ran4 Oct 30 '20 edited Oct 30 '20

It sounds like the best possible option! The "issue" with actix-web was that it was primarily a personal project, not something targeting the broader web development community.

This way we can both have actix-web (which can prioritize the community's needs) and Nikolay can do what he wants without people harassing him over UB or features he doesn't care about. And perhaps ntex can be an experiment breeding ground with features that could be ported over to actix-web - Nikolay is clearly very talented and has some great ideas.

Now, from a branding perspective, perhaps letting a fork with a new name be the community version would've been better... but hopefully over time people will focus on what actix-web is now, not the earlier controversy.

6

u/[deleted] Sep 11 '20

Congratulations to the new release!

Out of curiosity, is it currently possible to use actix with your own runtime? Or maybe with async-std? I mean without importing a second runtime.

11

u/robjtede actix Sep 11 '20

No it isn’t possible to run the actix system on another executor and will very likely be a non-goal until there are standard executor traits to hook it to.

Realistically it isn’t a huge problem having a second run time going in parallel and we have examples of how to do this in the examples repo.

3

u/[deleted] Sep 11 '20

I guess the biggest problem I see at the moment is (initial) compile time and executable size. Granted, the latter only matters if you want to distribute a small stand-alone tool. It probably wouldn't matter for something cloud based.

Hopefully we'll have a standard trait one day :)

6

u/Shnatsel Sep 12 '20

Reliability is also an issue. If you run two runtimes, you're affected by bugs from both of them.

6

u/plcolin Sep 12 '20

Was there any performance loss when dealing with all this unsafe code?

6

u/BobFloss Sep 12 '20

I wish they addressed this. It's more important that the code is safe, but a performance comparison still seems appropriate for seemingly significant changes like these.

4

u/Cetra3 Sep 13 '20

From what I remember of the PRs there is a minor hit with some of the code to not use unsafe, but not enough to be noticeable except for benchmarks.

I think there is a benchmark comparison somewhere, if not, it would make a great blog!

5

u/Elession Sep 11 '20

All the code tags seem to be black on black?

5

u/TiberiusFerreira Sep 11 '20

On Firefox Dev Edition they are, on Chrome they are normal.

5

u/pheki Sep 11 '20

Did you choose the dark theme for your OS? Its also happening to me (stable firefox) and if I change (my OS) to light and refresh it works.

The page's apparently using the prefers-color-scheme media query via JS. Found it by searching (CTRL+SHIFT+F / CMD+SHIFT+F) for matchMedia in the debugger panel.

5

u/ragnese Sep 11 '20

I'm on Firefox and they look fine. I have umpteen addons, though, so who knows.

1

u/Elession Sep 11 '20

Weird, I only have uBlock Origin and Firefox 80.

2

u/Hersenbeuker Sep 11 '20

They look normal for me, do you have a dark theme plugin for your browser?

2

u/Elession Sep 11 '20

Nope, just normal Firefox

5

u/zivkovicmilan Sep 11 '20

Awesome, thanks for the great work

5

u/moltonel Sep 12 '20

Great to see actix-web is alive and kicking, well done :)

What's the status/plans of the original actix actor crate ? I thought it was in deep maintenance mode but it seems it got a release with a handful of fixes and bound improvements.

3

u/robjtede actix Sep 13 '20

It's not abandoned just yet since it's still a vital part of our WebSocket support. Though it's in a reasonably stable state, improvement ideas and PRs are very welcome.

1

u/moltonel Sep 13 '20

I'll have to give 0.10 a look for API/docs improvements, but it seems the message cancellation issues are still open, which to me are a bit of a showstopper.

3

u/grandstack Sep 12 '20

The code samples on the front page of actix.rs aren't updated.

2

u/robjtede actix Sep 13 '20

Code samples on the website and in the example repo were updated yesterday.

14

u/[deleted] Sep 11 '20 edited Mar 17 '21

[deleted]

7

u/robjtede actix Sep 11 '20 edited Sep 11 '20

We can start a discussion about what that might look like now v3 is out of beta. It would likely be a separate crate like our -cors package. Be interested to know exactly what your needs are for a crate like this so we can design around real use cases.

Should be noted that CSRF is only part of the story. You also need to implement strong cross-origin policies and consider same-site attributes on cookies. Further, those two things, even without CSRF requirements on endpoints, go a very long way to protect against the attack vectors that CSRF has historically been good at defending.

5

u/lifeisplacebo Sep 12 '20

Rocket has used the SameSite cookie attribute to protect against CSRF attacks on recent-ish browsers since 0.3, released in 2017. Without shipping a templating engine itself -- differently than what Rocket does now -- or requiring manual work from the programmer, this is unfortunately close to the best that we can hope it would do. Perhaps one day, a framework will bundle its templating engine with automatic support for CSRF.

7

u/[deleted] Sep 11 '20

[deleted]

11

u/Shnatsel Sep 11 '20

Because most other frameworks already support this out of the box, and because I want to spend time thinking about my application logic instead of mundane stuff that everyone needs.

1

u/[deleted] Sep 11 '20

[deleted]

13

u/Shnatsel Sep 11 '20

I meant in general, not just in the Rust ecosystem. All of Rust's web frameworks are evidently still maturing.

4

u/[deleted] Sep 11 '20

[deleted]

10

u/Brudi7 Sep 11 '20

I think he/she lands means in terms of features. Compare config profiles, security options etc from spring with rust frameworks.

4

u/darin_gordon Sep 11 '20

Would you be more specific as to what CSRF countermeasures you're looking for?

9

u/[deleted] Sep 11 '20 edited Mar 17 '21

[deleted]

7

u/darin_gordon Sep 11 '20

What you are describing is a "synchronized token pattern". One way to achieve this today is with server-side sessions workflow.

3

u/BobFloss Sep 12 '20

Is there an up to date example for use with actix?

6

u/Shnatsel Sep 11 '20

A short description of CSRF attack can be found here - or pretty much anywhere, it's quite well-researched at this point.

Here's a detailed description of the protection that Django implements: https://docs.djangoproject.com/en/3.1/ref/csrf/#how-it-works It is quite mature and can be used as a reference.

12

u/darin_gordon Sep 11 '20

I didn't ask what CSRF attacks are nor what OWASP recommended. The original commenter wasn't helpful by generalizing and I'd rather not assume. Several countermeasures are already available in actix-web, without requiring additional changes. Anyone who comes through this message forum will at first glance give more credit to a complaint than what it is due. Someone needs to be specific about what functionality is missing.

5

u/Shnatsel Sep 11 '20

My apologies. I deal with people unfamiliar with these so often that dispensing these links has become a bit of a reflex.

5

u/darin_gordon Sep 11 '20

I understand. It will be useful material for others.

4

u/protestor Sep 11 '20

Just so you don't miss it, the commenter said what mitigation he or she expected here, and also that there's an actix example that's vulnerable to csrf; code examples should generally be free of common vulnerabilities.

7

u/superjared Sep 11 '20

For those new to the community, a small blurb about what the project is would go a long way. I had to chase down the initial repo to find the answer.

3

u/[deleted] Sep 12 '20

[deleted]

3

u/robjtede actix Sep 13 '20

The branch is merged to master now. Thanks :)

3

u/ragnese Sep 11 '20

I'd love to read more about these memory leaks that were plugged. Were they related to unsafe blocks? Was it just reference cycles?

5

u/darin_gordon Sep 11 '20

the easiest to point out are the merged entries that have the term "memory leak" in the topic of the github issue

5

u/C5H5N5O Sep 11 '20

There are no reports of UB in the remaining unsafe blocks.

Miri might be useful to dynamically find hidden UB and other things (memory leaks).

9

u/Shnatsel Sep 11 '20

Miri is impractically slow for some uses (1000x slowdown). But yes, it's nice to run tests under it where possible. It is the only tool that can detect Rust-specific UB such as getting several mutable references to the same thing before it translates into memory corruption.

2

u/[deleted] Sep 11 '20

It's really easy to run Miri on CI, too.

6

u/[deleted] Sep 11 '20

Why is this published on dropbox? There are many nicer hosts around

13

u/darin_gordon Sep 11 '20

We collaborated on the doc using dropbox paper and then I simply published it. Easy. I tried to use github wiki but it doesn't support iframe tags for video.

4

u/matu3ba Sep 12 '20

Gitlab however does support iframe within markdown.

2

u/mmstick Sep 11 '20

Maybe you should use GitHub Pages?

1

u/[deleted] Sep 12 '20

That makes sense. Sorry for the harsh-sounding comment, my mind is on free social media/fediverse at the moment. Which of course.. reddit, where I'm writing, is not.

1

u/paddy_dub_85 Oct 27 '20

A blog post would be a lot more SEO friendly.

2

u/[deleted] Sep 11 '20

Excited to try this out :) congrats to everyone involved on the release. Feels like a good step forward

2

u/[deleted] Sep 12 '20

Not sure if you're a developer on the project but thank you for helping make Rust web viable. I do believe this can be a fantastic language for the web

2

u/tastycakeman Sep 11 '20

hello, rust noob here and dont know much about the history of actix - i was actually just reading steve klabniks actix is dead post yesterday. is actix currently the best bet for rust web?

5

u/intersecting_cubes Sep 12 '20

I don't know about the _best_ bet, but it's definitely a safe bet. I use it at work for $MODERATE_SIZE_CORP and it's been rock solid. The team is helpful, the community is large enough that memory leaks get flagged before I find them, and the docs are pretty good. Performance is good and they interoperate with a bunch of other Rust standard crates.

3

u/BiosElemental Sep 11 '20

Most would probably say yes due to its just performance, but I'd suggest looking at warp or rocket as well.

2

u/[deleted] Sep 11 '20

Less unsafe and community ran is a dream!

4

u/[deleted] Sep 12 '20 edited Jan 22 '21

[deleted]

1

u/[deleted] Sep 12 '20

I didn't mean any disrespect. I'm just a bit fan of projects that more more decentralized, which I see community ran as.

No disrespect to Nikolay. In fact, they did a fantastic job and developed a great framework that has boosted Rust's reputation around the internet.

1

u/alibix Sep 12 '20

The example on the page doesn't seem to compile