more fancy talk about rust - sambaxp · rust intro. why? "th e [ samb a] p r o j e ct d o e s...

37
More Fancy Talk about Rust The allocator strikes back Kai Blin Samba Team SambaXP 2019 2019-06-06

Upload: others

Post on 05-Aug-2020

0 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

More Fancy Talk about RustThe allocator strikes back

Kai Blin Samba Team

SambaXP 2019 2019-06-06

Page 2: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Intro

M.Sc. in Computational Biology

Ph.D. in Microbiology

Samba Team member

Like to put Samba on small things

·

·

·

·

2/37

Page 3: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Intro

M.Sc. in Computational Biology

Ph.D. in Microbiology

Samba Team member

Like to put Samba on small things

·

·

·

·

3/37

Page 4: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Overview

Rust Intro

The Example Project

Challenges

Conclusions

·

·

·

·

4/37

Page 5: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

If someone claims to have the perfect programming language, he iseither a fool or a salesman or both. – Bjarne Stroustrup

Rust Intro

Page 6: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Why?

"The [Samba] project does need to consider the use of other, safer languages." – Jeremy Allison, SambaXP 2016

6/37

Page 7: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Why?No, honestly, why?

Avoid whole classes of bugs

New languages, new features

It's getting harder to find C programmers

·

·

·

7/37

Page 8: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

But why again?

Fell into the memory allocation rabbit hole last year

Solution I presented wasn't the popular choice afterwards

More on this in a bit

·

·

·

8/37

Page 9: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Rust

Announced 2010

C-like, compiled language

Focus on memory safety

Package management with cargo

Still a bit of a moving target

Programmers call themselves "Rustacians"

·

·

·

·

·

·

9/37

Page 10: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

RustHello, World!

fn main() {

println!("Hello, world!");

}

10/37

Page 11: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Introducing the example project.

Page 12: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

FancyTalk

A simple DNS-like protocol

Has a parser built in Rust

Built as a shared library

Loaded from a C application

·

·

·

·

12/37

Page 13: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

The FancyTalk Protocol

0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

| ID |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

|QR|BD|IT|UL|BL|Reserved| Red |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

| Green | Blue |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

| Query ... |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

| ... |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

| Payload ... |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

| ... |

+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+

13/37

Page 14: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

The FancyTalk Protocol

Client sends a query, giving an ID

Server looks up the query in the database

Server responds with a payload, using bit flags for formatting and fancycolours

·

·

·

14/37

Page 15: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Demo Time!

Server

Client

$ cd server

$ cargo run

$ cd client

$ cargo run 127.0.0.1 65432 greeting

15/37

Page 16: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

In theory, there is no difference between theory and practice. But, inpractice, there is. – Jan L. A. van de Snepscheut

Implementing it

Page 17: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Data structure

pub struct Package {

pub id: u16,

pub message_type: MessageType,

pub bold: bool,

pub italic: bool,

pub underlined: bool,

pub blink: bool,

pub red: u8,

pub green: u8,

pub blue: u8,

pub query: Option<String>,

pub payload: Option<String>,

}

pub enum MessageType {

Query,

Response,

}

17/37

Page 18: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Client

let mut query = Package::new();

query.query = Some(config.query);

let mut out_buf: Vec<u8> = Vec::new();

{

let mut encoder = Encoder::new(&mut out_buf);

query.write(&mut encoder).expect("Failed to encode query");

}

// send query

// get response

let mut decoder = Decoder::new(&in_buf);

let response = Package::read(&mut decoder).expect("Parsing the response failed");

// Format, colour and print response

18/37

Page 19: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Rust Server

loop {

// Receive query into inbuf

let mut decoder = Decoder::new(inbuf);

let query = Package::read(&mut decoder).expect("Parsing query failed");

let response = lookup_message(&mut messages, &query);

let mut outbuf: Vec<u8> = Vec::new();

{

let mut encoder = Encoder::new(&mut outbuf);

response.write(&mut encoder).expect("Encoding response failed");

}

// Send response from outbuf

}

19/37

Page 20: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

The C Server Concept

while True {

// Recieve query into in_buffer

// Call into Rust for parsing in_buf into Package

query = decode_package(in_buffer, len);

// "Business logic" in C

lookup_message(query, response);

// Call into Rust again to create out_buf for Package

encode_package(response, &out_buffer, &len);

// Send response from out_buffer

}

20/37

Page 21: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

The Shared API

typedef struct package {

//...

} Package;

Package *decode_package(const uint8_t* buffer, size_t len);

int encode_package(const Package *package, uint8_t **buffer, size_t *len);

21/37

Page 22: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Hang on a Moment

Who owns memory for the Package struct in decode_package()?

Option 1: Rust

Option 2: C

·

·

22/37

Page 23: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Option 1: Rust Owns Memory

Rust handles memory allocation

C just uses the structs

Rust needs to handle deallocation

C needs to call back into Rust to free memory

·

·

·

·

23/37

Page 24: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Remember the Free Functions

typedef struct package {

//...

} Package;

Package *decode_package(const uint8_t* buffer, size_t len);

int encode_package(const Package *package, uint8_t **buffer, size_t *len);

void free_package(Package *package);

void free_buffer(uint8_t *buffer);

Someone will forget to call the right free soon.·

24/37

Page 25: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Option 2: C Owns Memory

Memory ownership passed to calling C code

C takes care of freeing the memory

Rust needs to allocate memory in a way C can free

Idea: Port talloc to Rust

·

·

·

·

25/37

Page 26: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Rabbit Hole

Implementing talloc in Rust

This is where the project went offthe rails

Maybe let C handle the memoryafter all

·

·

26/37

Page 27: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Option 1: Rust Owns Memory

Rust handles memory allocation

C just uses the structs

Rust needs to handle deallocation

C needs to call back into Rust to free memory

Idea: Use talloc destructors

·

·

·

·

·

27/37

Page 28: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Old version with malloc

while(1) {

inbuf = malloc(MAX_UDP_SIZE);

buflen = recvfrom(...);

if (buflen == 0) { free(inbuf); continue; }

query = decode_package((uint8_t *)inbuf, buflen);

if (query == NULL) { free(inbuf); continue; }

response = lookup_message(messages, query);

free_package(query);

free(inbuf);

encode_package(response, &outbuf, &buflen);

buflen = sendto(...);

free_buffer(outbuf);

}

28/37

Page 29: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Old version ported to talloc

while(1) {

tmp_ctx = talloc_new(mem_ctx);

inbuf = talloc_size(tmp_ctx, MAX_UDP_SIZE);

buflen = recvfrom(...);

if (buflen == 0) { goto done; }

query = decode_package((uint8_t *)inbuf, buflen);

if (query == NULL) { goto done; }

response = lookup_message(messages, query);

encode_package(response, &outbuf, &buflen);

sendto(...);

done:

talloc_free(tmp_ctx);

free_package(query);

free_buffer(outbuf, buflen);

}

29/37

Page 30: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Using talloc destructorsSet up

struct server_ctx {

Package *query;

uint8_t *buffer;

uintptr_t buflen;

};

int free_server_ctx(struct server_ctx *srv) {

if (srv->query) {

free_package(srv->query);

}

if (srv->buffer) {

free_buffer(srv->buffer, srv->buflen);

}

};

30/37

Page 31: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Using talloc destructorsMain loop

while(1) {

srv_ctx = talloc_zero(mem_ctx, struct server_ctx);

talloc_set_destructor(srv_ctx, free_server_ctx);

inbuf = talloc_size(srv_ctx, MAX_UDP_SIZE);

buflen = recvfrom(...);

if (buflen == 0) { goto done; }

srv_ctx->query = decode_package((uint8_t *)inbuf, buflen);

if (srv_ctx->query == NULL) { goto done; }

response = lookup_message(messages, srv_ctx->query);

encode_package(response, &srv_ctx->buffer, &srv_ctx->buflen);

buflen = sendto(...);

done:

talloc_free(srv_ctx);

}

31/37

Page 32: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Demo Time!

Server

Client

$ cd c-server

$ make run

$ cd client

$ cargo run 127.0.0.1 6543 greeting

32/37

Page 33: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Caveats

incorrect free functions can still leak memory

FFI needs lots of unsafe blocks

ideally use opaque pointers for less glue code

·

·

·

33/37

Page 34: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Truth is subjectivity. – Søren Kierkegaard

Conclusions

Page 35: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Conclusions

How to integrate build systems?

How to handle Rust as dependency?

Rust community is pretty helpful, big thanks to mbrubeck, stefaneyfx andmatt1992

·

·

·

35/37

Page 36: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Future Work

Auto-generate code from IDL

Build system integration ☹

·

·

36/37

Page 37: More Fancy Talk about Rust - sambaXP · Rust Intro. Why? "Th e [ Samb a] p r o j e ct d o e s n e e d to co n si d e r th e u se o f o th e r , saf e r l an gu age s. " – J e r

Thank you