@@ -5,6 +5,9 @@ use std::ffi::CString;
5
5
use std:: thread;
6
6
7
7
fn 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 ( ) ;
8
11
let long_name = std:: iter:: once ( "test_named_thread_truncation" )
9
12
. chain ( std:: iter:: repeat ( " yada" ) . take ( 100 ) )
10
13
. collect :: < String > ( ) ;
@@ -48,23 +51,64 @@ fn main() {
48
51
}
49
52
}
50
53
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( ) ) ) ;
54
59
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 ) ;
61
64
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 ( ) ;
70
114
}
0 commit comments