Skip to content

Conversation

sunfishcode
Copy link
Member

Simplify Rust's command-line argument initialization code on unix:

  • The cleanup code isn't needed, because it was just zeroing out non-owning variables at runtime cleanup time. After 91c3eee, Rust's command-line initialization code on unix no longer allocates CStrings and a Vec at startup time.
  • The Mutex isn't needed; if there's somehow a call to args() before argument initialization has happened, the code returns return an empty list, which we can do with a null check.

With these changes, a simple cdylib that doesn't use threads avoids getting pthread_mutex_lock/pthread_mutex_unlock in its symbol table.

As of 91c3eee, the global ARGC and ARGV
no longer reference dynamically-allocated memory, so they don't need to
be cleaned up.
In the command-line argument initialization code, remove the Mutex
around the `ARGV` and `ARGC` variables, and simply check whether
ARGV is non-null before dereferencing it. This way, if either of
ARGV or ARGC is not initialized, we'll get an empty argument list.

This allows simple cdylibs to avoid having
`pthread_mutex_lock`/`pthread_mutex_unlock` appear in their symbol
tables if they don't otherwise use threads.
@rust-highfive
Copy link
Contributor

r? @kennytm

(rust-highfive has picked a reviewer for you, use r? to override)

@rust-highfive rust-highfive added the S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. label Jul 18, 2021
@rust-log-analyzer

This comment has been minimized.

@joshtriplett
Copy link
Member

@bors r+

@bors
Copy link
Collaborator

bors commented Jul 18, 2021

📌 Commit c3df0ae has been approved by joshtriplett

@bors bors added S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion. and removed S-waiting-on-review Status: Awaiting review from the assignee but also interested parties. labels Jul 18, 2021
let argv = ARGV.load(Ordering::Relaxed);
let argc = if argv.is_null() { 0 } else { ARGC.load(Ordering::Relaxed) };
Copy link
Member

Choose a reason for hiding this comment

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

Don't you need to do an acquire load (and a release store elsewhere) to ensure that the non-atomic load later (*argv.offset(i)) does not cause a data race?

Copy link
Member Author

Choose a reason for hiding this comment

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

I assume by this point the memory pointed to by argv is already ready to be loaded from without synchronization, since that's how C code would use argv.


unsafe fn really_init(argc: isize, argv: *const *const u8) {
let _guard = LOCK.lock();
ARGC.store(argc, Ordering::Relaxed);
ARGV.store(argv as *mut _, Ordering::Relaxed);
Copy link
Member

@RalfJung RalfJung Jul 18, 2021

Choose a reason for hiding this comment

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

This should probably be a release store to ensure that the writes to the data that sits behind this argv pointer are visible.

Copy link
Member Author

Choose a reason for hiding this comment

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

Those writes are performed before lang_start is called, by code that must assume that we may read from that memory immediately without atomics or synchronization.

For a spec reference, I found C11 5.1.2.2.1p2 which says the argv array is given values "prior to program startup".

Copy link
Member

Choose a reason for hiding this comment

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

So this is directly using the system-provided argc/argv, not something constructed by Rust itself? I guess it's technically correct then. But this seems subtle enough that it warrants a comment.

I'd probably still use release/acquire accesses. They are just more obviously correct. IMO Relaxed should only be used when there is a good perf reason to do so, and needs to come with comments explaining why not doing release/acquire is okay. Relaxed is a very subtle memory order that should not be used lightly.

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, this is the system-provided argc/argv. I submitted #87279 to address this.

bors added a commit to rust-lang-ci/rust that referenced this pull request Jul 19, 2021
…laumeGomez

Rollup of 8 pull requests

Successful merges:

 - rust-lang#86230 (Add --nocapture option to rustdoc)
 - rust-lang#87210 (Rustdoc accessibility: make the sidebar headers actual headers)
 - rust-lang#87227 (Move asm! and global_asm! to core::arch)
 - rust-lang#87236 (Simplify command-line argument initialization on unix)
 - rust-lang#87251 (Fix "item info" width)
 - rust-lang#87256 (Extend HIR-based WF checking to associated type defaults)
 - rust-lang#87259 (triagebot shortcut config)
 - rust-lang#87268 (Don't create references to uninitialized data in `List::from_arena`)

Failed merges:

r? `@ghost`
`@rustbot` modify labels: rollup
@bors bors merged commit 6df9df7 into rust-lang:master Jul 19, 2021
@rustbot rustbot added this to the 1.55.0 milestone Jul 19, 2021
@sunfishcode sunfishcode deleted the avoid-locking-args branch July 19, 2021 13:16
sunfishcode added a commit to sunfishcode/rust that referenced this pull request Jul 19, 2021
Following up on rust-lang#87236, add comments to the unix command-line argument
support explaining that the code doesn't mutate the system-provided
argc/argv, and that this is why the code doesn't need a lock or special
memory ordering.
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Jul 21, 2021
…alfJung

Add comments explaining the unix command-line argument support.

Following up on rust-lang#87236, add comments to the unix command-line argument
support explaining that the code doesn't mutate the system-provided
argc/argv, and that this is why the code doesn't need a lock or special
memory ordering.

r? `@RalfJung`
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this pull request Jul 21, 2021
…alfJung

Add comments explaining the unix command-line argument support.

Following up on rust-lang#87236, add comments to the unix command-line argument
support explaining that the code doesn't mutate the system-provided
argc/argv, and that this is why the code doesn't need a lock or special
memory ordering.

r? ``@RalfJung``
GuillaumeGomez added a commit to GuillaumeGomez/rust that referenced this pull request Jul 21, 2021
…alfJung

Add comments explaining the unix command-line argument support.

Following up on rust-lang#87236, add comments to the unix command-line argument
support explaining that the code doesn't mutate the system-provided
argc/argv, and that this is why the code doesn't need a lock or special
memory ordering.

r? ```@RalfJung```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
S-waiting-on-bors Status: Waiting on bors to run and complete tests. Bors will change the label on completion.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

8 participants