@@ -87,9 +87,9 @@ struct Settings {
87
87
/// A timer which triggers on a given interval
88
88
///
89
89
/// After being constructed with [`Alarm::with_interval`], [`Alarm::get_trigger`]
90
- /// will return [`TRIGGER_TIMER `] once per the given [`Duration`].
90
+ /// will return [`ALARM_TRIGGER_TIMER `] once per the given [`Duration`].
91
91
/// Alarm can be manually triggered with closure returned by [`Alarm::manual_trigger_fn`].
92
- /// [`Alarm::get_trigger`] will return [`TRIGGER_SIGNAL `] in this case.
92
+ /// [`Alarm::get_trigger`] will return [`ALARM_TRIGGER_SIGNAL `] in this case.
93
93
///
94
94
/// Can be cloned, but the trigger status is shared across all instances so only
95
95
/// the first caller each interval will yield true.
@@ -100,9 +100,9 @@ pub struct Alarm {
100
100
trigger : Arc < AtomicU8 > ,
101
101
}
102
102
103
- const TRIGGER_NONE : u8 = 0 ;
104
- const TRIGGER_TIMER : u8 = 1 ;
105
- const TRIGGER_SIGNAL : u8 = 2 ;
103
+ pub const ALARM_TRIGGER_NONE : u8 = 0 ;
104
+ pub const ALARM_TRIGGER_TIMER : u8 = 1 ;
105
+ pub const ALARM_TRIGGER_SIGNAL : u8 = 2 ;
106
106
107
107
impl Alarm {
108
108
pub fn with_interval ( interval : Duration ) -> Self {
@@ -112,7 +112,7 @@ impl Alarm {
112
112
thread:: spawn ( move || {
113
113
while let Some ( trigger) = weak_trigger. upgrade ( ) {
114
114
thread:: sleep ( interval) ;
115
- trigger. store ( TRIGGER_TIMER , Relaxed ) ;
115
+ trigger. store ( ALARM_TRIGGER_TIMER , Relaxed ) ;
116
116
}
117
117
} ) ;
118
118
@@ -123,13 +123,13 @@ impl Alarm {
123
123
let weak_trigger = Arc :: downgrade ( & self . trigger ) ;
124
124
Box :: new ( move || {
125
125
if let Some ( trigger) = weak_trigger. upgrade ( ) {
126
- trigger. store ( TRIGGER_SIGNAL , Relaxed ) ;
126
+ trigger. store ( ALARM_TRIGGER_SIGNAL , Relaxed ) ;
127
127
}
128
128
} )
129
129
}
130
130
131
131
pub fn get_trigger ( & self ) -> u8 {
132
- self . trigger . swap ( TRIGGER_NONE , Relaxed )
132
+ self . trigger . swap ( ALARM_TRIGGER_NONE , Relaxed )
133
133
}
134
134
135
135
pub fn get_interval ( & self ) -> Duration {
@@ -831,6 +831,30 @@ impl<'a> Output<'a> {
831
831
}
832
832
}
833
833
834
+ /// writes a block of data. optionally retries when first try didn't complete
835
+ ///
836
+ /// this is needed by gnu-test: tests/dd/stats.s
837
+ /// the write can be interrupted by a system signal.
838
+ /// e.g. SIGUSR1 which is send to report status
839
+ /// without retry, the data might not be fully written to destination.
840
+ fn write_block ( & mut self , chunk : & [ u8 ] ) -> io:: Result < usize > {
841
+ let full_len = chunk. len ( ) ;
842
+ let mut base_idx = 0 ;
843
+ loop {
844
+ match self . dst . write ( & chunk[ base_idx..] ) {
845
+ Ok ( wlen) => {
846
+ base_idx += wlen;
847
+ // take iflags.fullblock as oflags shall not have this option
848
+ if ( base_idx >= full_len) || !self . settings . iflags . fullblock {
849
+ return Ok ( base_idx) ;
850
+ }
851
+ }
852
+ Err ( e) if e. kind ( ) == io:: ErrorKind :: Interrupted => continue ,
853
+ Err ( e) => return Err ( e) ,
854
+ }
855
+ }
856
+ }
857
+
834
858
/// Write the given bytes one block at a time.
835
859
///
836
860
/// This may write partial blocks (for example, if the underlying
@@ -844,7 +868,7 @@ impl<'a> Output<'a> {
844
868
let mut bytes_total = 0 ;
845
869
846
870
for chunk in buf. chunks ( self . settings . obs ) {
847
- let wlen = self . dst . write ( chunk) ?;
871
+ let wlen = self . write_block ( chunk) ?;
848
872
if wlen < self . settings . obs {
849
873
writes_partial += 1 ;
850
874
} else {
@@ -1118,10 +1142,10 @@ fn dd_copy(mut i: Input, o: Output) -> std::io::Result<()> {
1118
1142
rstat += rstat_update;
1119
1143
wstat += wstat_update;
1120
1144
match alarm. get_trigger ( ) {
1121
- TRIGGER_NONE => { }
1122
- t @ TRIGGER_TIMER | t @ TRIGGER_SIGNAL => {
1145
+ ALARM_TRIGGER_NONE => { }
1146
+ t @ ALARM_TRIGGER_TIMER | t @ ALARM_TRIGGER_SIGNAL => {
1123
1147
let tp = match t {
1124
- TRIGGER_TIMER => ProgUpdateType :: Periodic ,
1148
+ ALARM_TRIGGER_TIMER => ProgUpdateType :: Periodic ,
1125
1149
_ => ProgUpdateType :: Signal ,
1126
1150
} ;
1127
1151
let prog_update = ProgUpdate :: new ( rstat, wstat, start. elapsed ( ) , tp) ;
0 commit comments