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

Basic 'Hello World' Port/Channel example causes abort/memory leak #1155

Closed
jhferris opened this issue Nov 8, 2011 · 8 comments
Closed

Basic 'Hello World' Port/Channel example causes abort/memory leak #1155

jhferris opened this issue Nov 8, 2011 · 8 comments
Assignees
Labels
A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows C-cleanup Category: PRs that clean code up or issues documenting cleanup.

Comments

@jhferris
Copy link

jhferris commented Nov 8, 2011

I tried to run the example code from the top of lib/comm.rs (here, for your convenience: http://pastebin.com/kwhhMK3Z)

Output of rustc --version:
rustc prerelease (06d14f3 2011-11-07 15:46:00 -0800)
host: i686-unknown-linux-gnu

OS: Ubuntu 11.10, amd64

Error Message:
rust: fatal, 'leaked memory in rust main loop (1 objects)' failed, ./src/rt/memory_region.cpp:131 1 objects
Aborted

FWIW, I tried taking out the argv, that was not the cause. Its my first time using rust, so its possible I did something wrong, but I figured I'd be cautious and open a bug.

@brson
Copy link
Contributor

brson commented Nov 8, 2011

This is cute. By default log is turned off, and doesn't evaluate its arguments, so recv isn't even being called. Combine that with the fact that we don't clean up our queues when data gets left in them and the "Hello World" string gets leaked. I bet if you changed 'log' to 'log_err' it would work as expected.

I think we should fix the example to be less error prone and properly clean up the port queues when they die.

@ghost ghost assigned brson Nov 8, 2011
@jhferris
Copy link
Author

jhferris commented Nov 8, 2011

Partially for my own edification, I just spent a few minutes poking around in the rt/ folder trying to get a handle on this bug/how ports & channels are structured internally. When the string is sent from the channel, it's buffered by the channel until one if its ports calls recv? And if there are >1 ports bound to one channel, only one port will ever recv "Hello World", or is it broadcast to everyone?

If my understanding is correct, this bug would get fixed by modifying the destructor in rt/rust_chan.cpp?

@jhferris
Copy link
Author

jhferris commented Nov 8, 2011

also how do I enable log, for future reference? My understanding is that its somewhat of a language builtin?

@brson
Copy link
Contributor

brson commented Nov 8, 2011

There's a section in the usage FAQ about enabling logging: https://github.com/graydon/rust/wiki/Usage-FAQ and there is some additional information in the language reference documentation.

There is only ever one port associated with a given channel, but there may be any number of channels associated with a port. It looks like messages are queued in individual channels. The fix here is that the rust_chan destructor needs to run the drop glue of the channel's element type on every element in the queue.

This presents some problems in that the channel doesn't currently know the type descriptor of the type it contains, and because channels can be sent across tasks, but type descriptors can't. Looks like a bit of a mess - probably we can just pull the drop glue function out of the type descriptor and store it with the channel instead of the entire type descriptor. But now that I think of it, we aren't going to be able to run the drop glue from C++ code once we have split stacks.

Maybe instead of drop glue we should just walk the shape of the type, like the cycle collector.

As a stopgop, we could just call kernel->free() on every element when we know that they are pointers. That would at least fix this problem with strings, vectors and unique boxes. It would not fix the problem with structural types that contain pointers though.

@brson
Copy link
Contributor

brson commented Nov 8, 2011

Both this and #1038 require tydescs that can move between tasks

brson added a commit that referenced this issue Nov 10, 2011
Due to a bug in channel destructors this examples fails when logging is off

Issue #1155
@brson brson closed this as completed in 138d9ca Nov 13, 2011
@brson
Copy link
Contributor

brson commented Nov 13, 2011

This turned out to be easier than expected because all the queuing actually happens on the port side, so it was just a matter of draining the queue (in rust code) when the port dies.

@brson
Copy link
Contributor

brson commented Nov 14, 2011

Reopening. There are still two cases that aren't covered:

  1. Ports are refcounted, so task A can take a ref, task B can run the Rust-side port destructor, then task A can send to the port and drop the ref.

  2. I don't know what happens when you try to send after the port doesn't exist

@brson brson reopened this Nov 14, 2011
@brson
Copy link
Contributor

brson commented Nov 14, 2011

2 is fixed by 5b9f76e

@brson brson reopened this Nov 15, 2011
@brson brson reopened this Nov 16, 2011
@brson brson closed this as completed Nov 17, 2011
celinval pushed a commit to celinval/rust-dev that referenced this issue Jun 4, 2024
Update code of conduct and security policy
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-runtime Area: std's runtime and "pre-main" init for handling backtraces, unwinds, stack overflows C-cleanup Category: PRs that clean code up or issues documenting cleanup.
Projects
None yet
Development

No branches or pull requests

2 participants