Skip to content

Commit 3aec9f4

Browse files
committed
native, rustuv: Fix spawning with empty args
There was a bug in both libnative and libuv which prevented child processes from being spawned correctly on windows when one of the arguments was an empty string. The libuv bug has since been fixed upstream, and the libnative bug was fixed as part of this commit. When updating libuv, this also includes a fix for rust-lang#15149. Closes rust-lang#15149 Closes rust-lang#16272
1 parent ce83301 commit 3aec9f4

File tree

6 files changed

+61
-11
lines changed

6 files changed

+61
-11
lines changed

src/libnative/io/process.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -479,7 +479,10 @@ fn make_command_line(prog: &CString, args: &[CString]) -> String {
479479
return cmd;
480480

481481
fn append_arg(cmd: &mut String, arg: &str) {
482-
let quote = arg.chars().any(|c| c == ' ' || c == '\t');
482+
// If an argument has 0 characters then we need to quote it to ensure
483+
// that it actually gets passed through on the command line or otherwise
484+
// it will be dropped entirely when parsed on the other end.
485+
let quote = arg.chars().any(|c| c == ' ' || c == '\t') || arg.len() == 0;
483486
if quote {
484487
cmd.push_char('"');
485488
}

src/librustuv/net.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ fn socket_name(sk: SocketNameKind,
137137

138138
let sockaddr_p = &mut sockaddr as *mut libc::sockaddr_storage;
139139
match unsafe {
140-
getsockname(handle, sockaddr_p as *mut libc::sockaddr, &mut namelen)
140+
getsockname(&*handle, sockaddr_p as *mut libc::sockaddr, &mut namelen)
141141
} {
142142
0 => Ok(sockaddr_to_addr(&sockaddr, namelen as uint)),
143143
n => Err(uv_error_to_io_error(UvError(n)))
@@ -365,7 +365,7 @@ impl TcpListener {
365365
let _len = addr_to_sockaddr(address, &mut storage);
366366
let res = unsafe {
367367
let addr_p = &storage as *const _ as *const libc::sockaddr;
368-
uvll::uv_tcp_bind(l.handle, addr_p)
368+
uvll::uv_tcp_bind(l.handle, addr_p, 0)
369369
};
370370
return match res {
371371
0 => Ok(l.install()),

src/librustuv/uvll.rs

+8-4
Original file line numberDiff line numberDiff line change
@@ -312,6 +312,7 @@ pub enum uv_req_type {
312312
UV_FS,
313313
UV_WORK,
314314
UV_GETADDRINFO,
315+
UV_GETNAMEINFO,
315316
UV_REQ_TYPE_MAX
316317
}
317318

@@ -329,6 +330,7 @@ pub enum uv_req_type {
329330
UV_UDP_SEND,
330331
UV_FS,
331332
UV_WORK,
333+
UV_GETNAMEINFO,
332334
UV_GETADDRINFO,
333335
UV_ACCEPT,
334336
UV_FS_EVENT_REQ,
@@ -578,14 +580,16 @@ extern {
578580
pub fn uv_tcp_init(l: *mut uv_loop_t, h: *mut uv_tcp_t) -> c_int;
579581
pub fn uv_tcp_connect(c: *mut uv_connect_t, h: *mut uv_tcp_t,
580582
addr: *const sockaddr, cb: uv_connect_cb) -> c_int;
581-
pub fn uv_tcp_bind(t: *mut uv_tcp_t, addr: *const sockaddr) -> c_int;
583+
pub fn uv_tcp_bind(t: *mut uv_tcp_t,
584+
addr: *const sockaddr,
585+
flags: c_uint) -> c_int;
582586
pub fn uv_tcp_nodelay(h: *mut uv_tcp_t, enable: c_int) -> c_int;
583587
pub fn uv_tcp_keepalive(h: *mut uv_tcp_t, enable: c_int,
584588
delay: c_uint) -> c_int;
585589
pub fn uv_tcp_simultaneous_accepts(h: *mut uv_tcp_t, enable: c_int) -> c_int;
586-
pub fn uv_tcp_getsockname(h: *mut uv_tcp_t, name: *mut sockaddr,
590+
pub fn uv_tcp_getsockname(h: *const uv_tcp_t, name: *mut sockaddr,
587591
len: *mut c_int) -> c_int;
588-
pub fn uv_tcp_getpeername(h: *mut uv_tcp_t, name: *mut sockaddr,
592+
pub fn uv_tcp_getpeername(h: *const uv_tcp_t, name: *mut sockaddr,
589593
len: *mut c_int) -> c_int;
590594

591595
// udp bindings
@@ -604,7 +608,7 @@ extern {
604608
pub fn uv_udp_set_multicast_ttl(handle: *mut uv_udp_t, ttl: c_int) -> c_int;
605609
pub fn uv_udp_set_ttl(handle: *mut uv_udp_t, ttl: c_int) -> c_int;
606610
pub fn uv_udp_set_broadcast(handle: *mut uv_udp_t, on: c_int) -> c_int;
607-
pub fn uv_udp_getsockname(h: *mut uv_udp_t, name: *mut sockaddr,
611+
pub fn uv_udp_getsockname(h: *const uv_udp_t, name: *mut sockaddr,
608612
len: *mut c_int) -> c_int;
609613

610614
// timer bindings

src/libuv

Submodule libuv updated from 4349589 to dec0561

src/test/run-pass/issue-15149.rs

+1-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,7 @@ use std::io::{TempDir, Command, fs};
1818
use std::os;
1919
use std::task::TaskBuilder;
2020

21-
// FIXME(#15149) libgreen still needs to be update. There is an open PR for it
22-
// but it is not yet merged.
23-
// green_start!(main)
21+
green_start!(main)
2422

2523
fn main() {
2624
// If we're the child, make sure we were invoked correctly

src/test/run-pass/issue-16272.rs

+45
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#![feature(phase)]
12+
#[phase(plugin)]
13+
extern crate green;
14+
extern crate native;
15+
16+
use native::NativeTaskBuilder;
17+
use std::io::{process, Command};
18+
use std::os;
19+
use std::task::TaskBuilder;
20+
21+
green_start!(main)
22+
23+
fn main() {
24+
let len = os::args().len();
25+
26+
if len == 1 {
27+
test();
28+
let (tx, rx) = channel();
29+
TaskBuilder::new().native().spawn(proc() {
30+
tx.send(test());
31+
});
32+
rx.recv();
33+
} else {
34+
assert_eq!(len, 3);
35+
}
36+
}
37+
38+
fn test() {
39+
let status = Command::new(os::self_exe_name().unwrap())
40+
.arg("foo").arg("")
41+
.stdout(process::InheritFd(1))
42+
.stderr(process::InheritFd(2))
43+
.status().unwrap();
44+
assert!(status.success());
45+
}

0 commit comments

Comments
 (0)