@@ -152,6 +152,24 @@ fn absolute(path: &Path) -> PathBuf {
152
152
}
153
153
}
154
154
155
+ #[ derive( Debug , Fail ) ]
156
+ pub ( crate ) enum DockerError {
157
+ #[ fail( display = "container ran out of memory" ) ]
158
+ ContainerOOM ,
159
+ }
160
+
161
+ #[ derive( Deserialize ) ]
162
+ #[ serde( rename_all = "PascalCase" ) ]
163
+ struct InspectContainer {
164
+ state : InspectState ,
165
+ }
166
+
167
+ #[ derive( Deserialize ) ]
168
+ struct InspectState {
169
+ #[ serde( rename = "OOMKilled" ) ]
170
+ oom_killed : bool ,
171
+ }
172
+
155
173
#[ derive( Serialize , Deserialize , Clone , Debug ) ]
156
174
pub ( crate ) struct Container {
157
175
// Docker container ID
@@ -165,11 +183,34 @@ impl Display for Container {
165
183
}
166
184
167
185
impl Container {
186
+ fn inspect ( & self ) -> Fallible < InspectContainer > {
187
+ let output = RunCommand :: new ( "docker" )
188
+ . args ( & [ "inspect" , & self . id ] )
189
+ . hide_output ( true )
190
+ . run_capture ( ) ?;
191
+
192
+ let mut data: Vec < InspectContainer > = :: serde_json:: from_str ( & output. 0 . join ( "\n " ) ) ?;
193
+ assert_eq ! ( data. len( ) , 1 ) ;
194
+ Ok ( data. pop ( ) . unwrap ( ) )
195
+ }
196
+
168
197
pub ( crate ) fn run ( & self , quiet : bool ) -> Fallible < ( ) > {
169
- RunCommand :: new ( "docker" )
198
+ let res = RunCommand :: new ( "docker" )
170
199
. args ( & [ "start" , "-a" , & self . id ] )
171
200
. quiet ( quiet)
172
- . run ( )
201
+ . run ( ) ;
202
+ let details = self . inspect ( ) ?;
203
+
204
+ // Return a different error if the container was killed due to an OOM
205
+ if details. state . oom_killed {
206
+ if let Err ( err) = res {
207
+ Err ( err. context ( DockerError :: ContainerOOM ) . into ( ) )
208
+ } else {
209
+ Err ( DockerError :: ContainerOOM . into ( ) )
210
+ }
211
+ } else {
212
+ res
213
+ }
173
214
}
174
215
175
216
pub ( crate ) fn delete ( & self ) -> Fallible < ( ) > {
0 commit comments