@@ -5,6 +5,9 @@ use std::ffi::CString;
55use std:: thread;
66
77fn main ( ) {
8+ // The short name should be shorter than 16 bytes which POSIX promises
9+ // for thread names. The length includes a null terminator.
10+ let short_name = "test_named" . to_owned ( ) ;
811 let long_name = std:: iter:: once ( "test_named_thread_truncation" )
912 . chain ( std:: iter:: repeat ( " yada" ) . take ( 100 ) )
1013 . collect :: < String > ( ) ;
@@ -48,23 +51,64 @@ fn main() {
4851 }
4952 }
5053
51- let result = thread:: Builder :: new ( ) . name ( long_name. clone ( ) ) . spawn ( move || {
52- // Rust remembers the full thread name itself.
53- assert_eq ! ( thread:: current( ) . name( ) , Some ( long_name. as_str( ) ) ) ;
54+ thread:: Builder :: new ( )
55+ . name ( short_name. clone ( ) )
56+ . spawn ( move || {
57+ // Rust remembers the full thread name itself.
58+ assert_eq ! ( thread:: current( ) . name( ) , Some ( short_name. as_str( ) ) ) ;
5459
55- // But the system is limited -- make sure we successfully set a truncation.
56- let mut buf = vec ! [ 0u8 ; long_name. len( ) + 1 ] ;
57- assert_eq ! ( get_thread_name( & mut buf) , 0 ) ;
58- let cstr = CStr :: from_bytes_until_nul ( & buf) . unwrap ( ) ;
59- assert ! ( cstr. to_bytes( ) . len( ) >= 15 , "name is too short: len={}" , cstr. to_bytes( ) . len( ) ) ; // POSIX seems to promise at least 15 chars
60- assert ! ( long_name. as_bytes( ) . starts_with( cstr. to_bytes( ) ) ) ;
60+ // Note that glibc requires 15 bytes long buffer exculding a null terminator.
61+ // Otherwise, `pthread_getname_np` returns an error.
62+ let mut buf = vec ! [ 0u8 ; short_name. len( ) . max( 15 ) + 1 ] ;
63+ assert_eq ! ( get_thread_name( & mut buf) , 0 ) ;
6164
62- // Also test directly calling pthread_setname to check its return value.
63- assert_eq ! ( set_thread_name( & cstr) , 0 ) ;
64- // But with a too long name it should fail (except on FreeBSD where the
65- // function has no return, hence cannot indicate failure).
66- #[ cfg( not( target_os = "freebsd" ) ) ]
67- assert_ne ! ( set_thread_name( & CString :: new( long_name) . unwrap( ) ) , 0 ) ;
68- } ) ;
69- result. unwrap ( ) . join ( ) . unwrap ( ) ;
65+ let cstr = CStr :: from_bytes_until_nul ( & buf) . unwrap ( ) ;
66+ // POSIX seems to promise at least 15 chars excluding a null terminator.
67+ assert_eq ! ( short_name. as_bytes( ) , cstr. to_bytes( ) ) ;
68+
69+ // Also test directly calling pthread_setname to check its return value.
70+ assert_eq ! ( set_thread_name( & cstr) , 0 ) ;
71+
72+ // For glibc used by linux-gnu there should be a failue,
73+ // if a shorter than 16 bytes buffer is provided, even if that would be
74+ // large enough for the thread name.
75+ #[ cfg( target_os = "linux" ) ]
76+ assert_eq ! ( get_thread_name( & mut buf[ ..15 ] ) , libc:: ERANGE ) ;
77+ } )
78+ . unwrap ( )
79+ . join ( )
80+ . unwrap ( ) ;
81+
82+ thread:: Builder :: new ( )
83+ . name ( long_name. clone ( ) )
84+ . spawn ( move || {
85+ // Rust remembers the full thread name itself.
86+ assert_eq ! ( thread:: current( ) . name( ) , Some ( long_name. as_str( ) ) ) ;
87+
88+ // But the system is limited -- make sure we successfully set a truncation.
89+ // Note that there's no specific to glibc buffer requirement, since the value
90+ // `long_name` is longer than 16 bytes including a null terminator.
91+ let mut buf = vec ! [ 0u8 ; long_name. len( ) + 1 ] ;
92+ assert_eq ! ( get_thread_name( & mut buf) , 0 ) ;
93+
94+ let cstr = CStr :: from_bytes_until_nul ( & buf) . unwrap ( ) ;
95+ // POSIX seems to promise at least 15 chars excluding a null terminator.
96+ assert ! (
97+ cstr. to_bytes( ) . len( ) >= 15 ,
98+ "name is too short: len={}" ,
99+ cstr. to_bytes( ) . len( )
100+ ) ;
101+ assert ! ( long_name. as_bytes( ) . starts_with( cstr. to_bytes( ) ) ) ;
102+
103+ // Also test directly calling pthread_setname to check its return value.
104+ assert_eq ! ( set_thread_name( & cstr) , 0 ) ;
105+
106+ // But with a too long name it should fail (except on FreeBSD where the
107+ // function has no return, hence cannot indicate failure).
108+ #[ cfg( not( target_os = "freebsd" ) ) ]
109+ assert_ne ! ( set_thread_name( & CString :: new( long_name) . unwrap( ) ) , 0 ) ;
110+ } )
111+ . unwrap ( )
112+ . join ( )
113+ . unwrap ( ) ;
70114}
0 commit comments