Signed-off-by: Brian Goff <cpuguy83@gmail.com>
| ... | ... |
@@ -1,5 +1,5 @@ |
| 1 | 1 |
github.com/Azure/go-ansiterm d6e3b3328b783f23731bc4d058875b0371ff8109 |
| 2 |
-github.com/Microsoft/hcsshim 9dcb42f100215f8d375b4a9265e5bba009217a85 # moby branch |
|
| 2 |
+github.com/Microsoft/hcsshim 89a9a3b524264d34985f1d48793ab2b2d2e430f6 # moby branch |
|
| 3 | 3 |
github.com/Microsoft/go-winio 5b44b70ab3ab4d291a7c1d28afe7b4afeced0ed4 # v0.4.15 |
| 4 | 4 |
github.com/docker/libtrust 9cbd2a1374f46905c68a4eb3694a130610adc62a |
| 5 | 5 |
github.com/golang/gddo 72a348e765d293ed6d1ded7b699591f14d6cd921 |
| ... | ... |
@@ -83,7 +83,6 @@ type NetworkNotFoundError = hns.NetworkNotFoundError |
| 83 | 83 |
type ProcessError struct {
|
| 84 | 84 |
Process *process |
| 85 | 85 |
Operation string |
| 86 |
- ExtraInfo string |
|
| 87 | 86 |
Err error |
| 88 | 87 |
Events []hcs.ErrorEvent |
| 89 | 88 |
} |
| ... | ... |
@@ -92,7 +91,6 @@ type ProcessError struct {
|
| 92 | 92 |
type ContainerError struct {
|
| 93 | 93 |
Container *container |
| 94 | 94 |
Operation string |
| 95 |
- ExtraInfo string |
|
| 96 | 95 |
Err error |
| 97 | 96 |
Events []hcs.ErrorEvent |
| 98 | 97 |
} |
| ... | ... |
@@ -125,10 +123,6 @@ func (e *ContainerError) Error() string {
|
| 125 | 125 |
s += "\n" + ev.String() |
| 126 | 126 |
} |
| 127 | 127 |
|
| 128 |
- if e.ExtraInfo != "" {
|
|
| 129 |
- s += " extra info: " + e.ExtraInfo |
|
| 130 |
- } |
|
| 131 |
- |
|
| 132 | 128 |
return s |
| 133 | 129 |
} |
| 134 | 130 |
|
| ... | ... |
@@ -137,7 +131,7 @@ func makeContainerError(container *container, operation string, extraInfo string |
| 137 | 137 |
if _, ok := err.(*ContainerError); ok {
|
| 138 | 138 |
return err |
| 139 | 139 |
} |
| 140 |
- containerError := &ContainerError{Container: container, Operation: operation, ExtraInfo: extraInfo, Err: err}
|
|
| 140 |
+ containerError := &ContainerError{Container: container, Operation: operation, Err: err}
|
|
| 141 | 141 |
return containerError |
| 142 | 142 |
} |
| 143 | 143 |
|
| ... | ... |
@@ -176,7 +170,7 @@ func makeProcessError(process *process, operation string, extraInfo string, err |
| 176 | 176 |
if _, ok := err.(*ProcessError); ok {
|
| 177 | 177 |
return err |
| 178 | 178 |
} |
| 179 |
- processError := &ProcessError{Process: process, Operation: operation, ExtraInfo: extraInfo, Err: err}
|
|
| 179 |
+ processError := &ProcessError{Process: process, Operation: operation, Err: err}
|
|
| 180 | 180 |
return processError |
| 181 | 181 |
} |
| 182 | 182 |
|
| ... | ... |
@@ -244,7 +238,7 @@ func getInnerError(err error) error {
|
| 244 | 244 |
|
| 245 | 245 |
func convertSystemError(err error, c *container) error {
|
| 246 | 246 |
if serr, ok := err.(*hcs.SystemError); ok {
|
| 247 |
- return &ContainerError{Container: c, Operation: serr.Op, ExtraInfo: serr.Extra, Err: serr.Err, Events: serr.Events}
|
|
| 247 |
+ return &ContainerError{Container: c, Operation: serr.Op, Err: serr.Err, Events: serr.Events}
|
|
| 248 | 248 |
} |
| 249 | 249 |
return err |
| 250 | 250 |
} |
| ... | ... |
@@ -171,7 +171,6 @@ type SystemError struct {
|
| 171 | 171 |
ID string |
| 172 | 172 |
Op string |
| 173 | 173 |
Err error |
| 174 |
- Extra string |
|
| 175 | 174 |
Events []ErrorEvent |
| 176 | 175 |
} |
| 177 | 176 |
|
| ... | ... |
@@ -182,9 +181,6 @@ func (e *SystemError) Error() string {
|
| 182 | 182 |
for _, ev := range e.Events {
|
| 183 | 183 |
s += "\n" + ev.String() |
| 184 | 184 |
} |
| 185 |
- if e.Extra != "" {
|
|
| 186 |
- s += "\n(extra info: " + e.Extra + ")" |
|
| 187 |
- } |
|
| 188 | 185 |
return s |
| 189 | 186 |
} |
| 190 | 187 |
|
| ... | ... |
@@ -198,7 +194,7 @@ func (e *SystemError) Timeout() bool {
|
| 198 | 198 |
return ok && err.Timeout() |
| 199 | 199 |
} |
| 200 | 200 |
|
| 201 |
-func makeSystemError(system *System, op string, extra string, err error, events []ErrorEvent) error {
|
|
| 201 |
+func makeSystemError(system *System, op string, err error, events []ErrorEvent) error {
|
|
| 202 | 202 |
// Don't double wrap errors |
| 203 | 203 |
if _, ok := err.(*SystemError); ok {
|
| 204 | 204 |
return err |
| ... | ... |
@@ -206,7 +202,6 @@ func makeSystemError(system *System, op string, extra string, err error, events |
| 206 | 206 |
return &SystemError{
|
| 207 | 207 |
ID: system.ID(), |
| 208 | 208 |
Op: op, |
| 209 |
- Extra: extra, |
|
| 210 | 209 |
Err: err, |
| 211 | 210 |
Events: events, |
| 212 | 211 |
} |
| ... | ... |
@@ -75,7 +75,7 @@ func CreateComputeSystem(ctx context.Context, id string, hcsDocumentInterface in |
| 75 | 75 |
// Terminate the compute system if it still exists. We're okay to |
| 76 | 76 |
// ignore a failure here. |
| 77 | 77 |
computeSystem.Terminate(ctx) |
| 78 |
- return nil, makeSystemError(computeSystem, operation, "", err, nil) |
|
| 78 |
+ return nil, makeSystemError(computeSystem, operation, err, nil) |
|
| 79 | 79 |
} |
| 80 | 80 |
} |
| 81 | 81 |
|
| ... | ... |
@@ -86,7 +86,7 @@ func CreateComputeSystem(ctx context.Context, id string, hcsDocumentInterface in |
| 86 | 86 |
// ignore a failure here. |
| 87 | 87 |
computeSystem.Terminate(ctx) |
| 88 | 88 |
} |
| 89 |
- return nil, makeSystemError(computeSystem, operation, hcsDocument, err, events) |
|
| 89 |
+ return nil, makeSystemError(computeSystem, operation, err, events) |
|
| 90 | 90 |
} |
| 91 | 91 |
go computeSystem.waitBackground() |
| 92 | 92 |
if err = computeSystem.getCachedProperties(ctx); err != nil {
|
| ... | ... |
@@ -103,7 +103,7 @@ func OpenComputeSystem(ctx context.Context, id string) (*System, error) {
|
| 103 | 103 |
handle, resultJSON, err := vmcompute.HcsOpenComputeSystem(ctx, id) |
| 104 | 104 |
events := processHcsResult(ctx, resultJSON) |
| 105 | 105 |
if err != nil {
|
| 106 |
- return nil, makeSystemError(computeSystem, operation, "", err, events) |
|
| 106 |
+ return nil, makeSystemError(computeSystem, operation, err, events) |
|
| 107 | 107 |
} |
| 108 | 108 |
computeSystem.handle = handle |
| 109 | 109 |
defer func() {
|
| ... | ... |
@@ -112,7 +112,7 @@ func OpenComputeSystem(ctx context.Context, id string) (*System, error) {
|
| 112 | 112 |
} |
| 113 | 113 |
}() |
| 114 | 114 |
if err = computeSystem.registerCallback(ctx); err != nil {
|
| 115 |
- return nil, makeSystemError(computeSystem, operation, "", err, nil) |
|
| 115 |
+ return nil, makeSystemError(computeSystem, operation, err, nil) |
|
| 116 | 116 |
} |
| 117 | 117 |
go computeSystem.waitBackground() |
| 118 | 118 |
if err = computeSystem.getCachedProperties(ctx); err != nil {
|
| ... | ... |
@@ -188,13 +188,13 @@ func (computeSystem *System) Start(ctx context.Context) (err error) {
|
| 188 | 188 |
defer computeSystem.handleLock.RUnlock() |
| 189 | 189 |
|
| 190 | 190 |
if computeSystem.handle == 0 {
|
| 191 |
- return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) |
|
| 191 |
+ return makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil) |
|
| 192 | 192 |
} |
| 193 | 193 |
|
| 194 | 194 |
resultJSON, err := vmcompute.HcsStartComputeSystem(ctx, computeSystem.handle, "") |
| 195 | 195 |
events, err := processAsyncHcsResult(ctx, err, resultJSON, computeSystem.callbackNumber, hcsNotificationSystemStartCompleted, &timeout.SystemStart) |
| 196 | 196 |
if err != nil {
|
| 197 |
- return makeSystemError(computeSystem, operation, "", err, events) |
|
| 197 |
+ return makeSystemError(computeSystem, operation, err, events) |
|
| 198 | 198 |
} |
| 199 | 199 |
|
| 200 | 200 |
return nil |
| ... | ... |
@@ -221,7 +221,7 @@ func (computeSystem *System) Shutdown(ctx context.Context) error {
|
| 221 | 221 |
switch err {
|
| 222 | 222 |
case nil, ErrVmcomputeAlreadyStopped, ErrComputeSystemDoesNotExist, ErrVmcomputeOperationPending: |
| 223 | 223 |
default: |
| 224 |
- return makeSystemError(computeSystem, operation, "", err, events) |
|
| 224 |
+ return makeSystemError(computeSystem, operation, err, events) |
|
| 225 | 225 |
} |
| 226 | 226 |
return nil |
| 227 | 227 |
} |
| ... | ... |
@@ -242,7 +242,7 @@ func (computeSystem *System) Terminate(ctx context.Context) error {
|
| 242 | 242 |
switch err {
|
| 243 | 243 |
case nil, ErrVmcomputeAlreadyStopped, ErrComputeSystemDoesNotExist, ErrVmcomputeOperationPending: |
| 244 | 244 |
default: |
| 245 |
- return makeSystemError(computeSystem, operation, "", err, events) |
|
| 245 |
+ return makeSystemError(computeSystem, operation, err, events) |
|
| 246 | 246 |
} |
| 247 | 247 |
return nil |
| 248 | 248 |
} |
| ... | ... |
@@ -264,10 +264,10 @@ func (computeSystem *System) waitBackground() {
|
| 264 | 264 |
log.G(ctx).Debug("system exited")
|
| 265 | 265 |
case ErrVmcomputeUnexpectedExit: |
| 266 | 266 |
log.G(ctx).Debug("unexpected system exit")
|
| 267 |
- computeSystem.exitError = makeSystemError(computeSystem, operation, "", err, nil) |
|
| 267 |
+ computeSystem.exitError = makeSystemError(computeSystem, operation, err, nil) |
|
| 268 | 268 |
err = nil |
| 269 | 269 |
default: |
| 270 |
- err = makeSystemError(computeSystem, operation, "", err, nil) |
|
| 270 |
+ err = makeSystemError(computeSystem, operation, err, nil) |
|
| 271 | 271 |
} |
| 272 | 272 |
computeSystem.closedWaitOnce.Do(func() {
|
| 273 | 273 |
computeSystem.waitError = err |
| ... | ... |
@@ -305,13 +305,13 @@ func (computeSystem *System) Properties(ctx context.Context, types ...schema1.Pr |
| 305 | 305 |
|
| 306 | 306 |
queryBytes, err := json.Marshal(schema1.PropertyQuery{PropertyTypes: types})
|
| 307 | 307 |
if err != nil {
|
| 308 |
- return nil, makeSystemError(computeSystem, operation, "", err, nil) |
|
| 308 |
+ return nil, makeSystemError(computeSystem, operation, err, nil) |
|
| 309 | 309 |
} |
| 310 | 310 |
|
| 311 | 311 |
propertiesJSON, resultJSON, err := vmcompute.HcsGetComputeSystemProperties(ctx, computeSystem.handle, string(queryBytes)) |
| 312 | 312 |
events := processHcsResult(ctx, resultJSON) |
| 313 | 313 |
if err != nil {
|
| 314 |
- return nil, makeSystemError(computeSystem, operation, "", err, events) |
|
| 314 |
+ return nil, makeSystemError(computeSystem, operation, err, events) |
|
| 315 | 315 |
} |
| 316 | 316 |
|
| 317 | 317 |
if propertiesJSON == "" {
|
| ... | ... |
@@ -319,7 +319,7 @@ func (computeSystem *System) Properties(ctx context.Context, types ...schema1.Pr |
| 319 | 319 |
} |
| 320 | 320 |
properties := &schema1.ContainerProperties{}
|
| 321 | 321 |
if err := json.Unmarshal([]byte(propertiesJSON), properties); err != nil {
|
| 322 |
- return nil, makeSystemError(computeSystem, operation, "", err, nil) |
|
| 322 |
+ return nil, makeSystemError(computeSystem, operation, err, nil) |
|
| 323 | 323 |
} |
| 324 | 324 |
|
| 325 | 325 |
return properties, nil |
| ... | ... |
@@ -334,13 +334,13 @@ func (computeSystem *System) PropertiesV2(ctx context.Context, types ...hcsschem |
| 334 | 334 |
|
| 335 | 335 |
queryBytes, err := json.Marshal(hcsschema.PropertyQuery{PropertyTypes: types})
|
| 336 | 336 |
if err != nil {
|
| 337 |
- return nil, makeSystemError(computeSystem, operation, "", err, nil) |
|
| 337 |
+ return nil, makeSystemError(computeSystem, operation, err, nil) |
|
| 338 | 338 |
} |
| 339 | 339 |
|
| 340 | 340 |
propertiesJSON, resultJSON, err := vmcompute.HcsGetComputeSystemProperties(ctx, computeSystem.handle, string(queryBytes)) |
| 341 | 341 |
events := processHcsResult(ctx, resultJSON) |
| 342 | 342 |
if err != nil {
|
| 343 |
- return nil, makeSystemError(computeSystem, operation, "", err, events) |
|
| 343 |
+ return nil, makeSystemError(computeSystem, operation, err, events) |
|
| 344 | 344 |
} |
| 345 | 345 |
|
| 346 | 346 |
if propertiesJSON == "" {
|
| ... | ... |
@@ -348,7 +348,7 @@ func (computeSystem *System) PropertiesV2(ctx context.Context, types ...hcsschem |
| 348 | 348 |
} |
| 349 | 349 |
properties := &hcsschema.Properties{}
|
| 350 | 350 |
if err := json.Unmarshal([]byte(propertiesJSON), properties); err != nil {
|
| 351 |
- return nil, makeSystemError(computeSystem, operation, "", err, nil) |
|
| 351 |
+ return nil, makeSystemError(computeSystem, operation, err, nil) |
|
| 352 | 352 |
} |
| 353 | 353 |
|
| 354 | 354 |
return properties, nil |
| ... | ... |
@@ -369,13 +369,13 @@ func (computeSystem *System) Pause(ctx context.Context) (err error) {
|
| 369 | 369 |
defer computeSystem.handleLock.RUnlock() |
| 370 | 370 |
|
| 371 | 371 |
if computeSystem.handle == 0 {
|
| 372 |
- return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) |
|
| 372 |
+ return makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil) |
|
| 373 | 373 |
} |
| 374 | 374 |
|
| 375 | 375 |
resultJSON, err := vmcompute.HcsPauseComputeSystem(ctx, computeSystem.handle, "") |
| 376 | 376 |
events, err := processAsyncHcsResult(ctx, err, resultJSON, computeSystem.callbackNumber, hcsNotificationSystemPauseCompleted, &timeout.SystemPause) |
| 377 | 377 |
if err != nil {
|
| 378 |
- return makeSystemError(computeSystem, operation, "", err, events) |
|
| 378 |
+ return makeSystemError(computeSystem, operation, err, events) |
|
| 379 | 379 |
} |
| 380 | 380 |
|
| 381 | 381 |
return nil |
| ... | ... |
@@ -396,13 +396,13 @@ func (computeSystem *System) Resume(ctx context.Context) (err error) {
|
| 396 | 396 |
defer computeSystem.handleLock.RUnlock() |
| 397 | 397 |
|
| 398 | 398 |
if computeSystem.handle == 0 {
|
| 399 |
- return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) |
|
| 399 |
+ return makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil) |
|
| 400 | 400 |
} |
| 401 | 401 |
|
| 402 | 402 |
resultJSON, err := vmcompute.HcsResumeComputeSystem(ctx, computeSystem.handle, "") |
| 403 | 403 |
events, err := processAsyncHcsResult(ctx, err, resultJSON, computeSystem.callbackNumber, hcsNotificationSystemResumeCompleted, &timeout.SystemResume) |
| 404 | 404 |
if err != nil {
|
| 405 |
- return makeSystemError(computeSystem, operation, "", err, events) |
|
| 405 |
+ return makeSystemError(computeSystem, operation, err, events) |
|
| 406 | 406 |
} |
| 407 | 407 |
|
| 408 | 408 |
return nil |
| ... | ... |
@@ -413,19 +413,19 @@ func (computeSystem *System) createProcess(ctx context.Context, operation string |
| 413 | 413 |
defer computeSystem.handleLock.RUnlock() |
| 414 | 414 |
|
| 415 | 415 |
if computeSystem.handle == 0 {
|
| 416 |
- return nil, nil, makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) |
|
| 416 |
+ return nil, nil, makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil) |
|
| 417 | 417 |
} |
| 418 | 418 |
|
| 419 | 419 |
configurationb, err := json.Marshal(c) |
| 420 | 420 |
if err != nil {
|
| 421 |
- return nil, nil, makeSystemError(computeSystem, operation, "", err, nil) |
|
| 421 |
+ return nil, nil, makeSystemError(computeSystem, operation, err, nil) |
|
| 422 | 422 |
} |
| 423 | 423 |
|
| 424 | 424 |
configuration := string(configurationb) |
| 425 | 425 |
processInfo, processHandle, resultJSON, err := vmcompute.HcsCreateProcess(ctx, computeSystem.handle, configuration) |
| 426 | 426 |
events := processHcsResult(ctx, resultJSON) |
| 427 | 427 |
if err != nil {
|
| 428 |
- return nil, nil, makeSystemError(computeSystem, operation, configuration, err, events) |
|
| 428 |
+ return nil, nil, makeSystemError(computeSystem, operation, err, events) |
|
| 429 | 429 |
} |
| 430 | 430 |
|
| 431 | 431 |
log.G(ctx).WithField("pid", processInfo.ProcessId).Debug("created process pid")
|
| ... | ... |
@@ -447,7 +447,7 @@ func (computeSystem *System) CreateProcess(ctx context.Context, c interface{}) (
|
| 447 | 447 |
|
| 448 | 448 |
pipes, err := makeOpenFiles([]syscall.Handle{processInfo.StdInput, processInfo.StdOutput, processInfo.StdError})
|
| 449 | 449 |
if err != nil {
|
| 450 |
- return nil, makeSystemError(computeSystem, operation, "", err, nil) |
|
| 450 |
+ return nil, makeSystemError(computeSystem, operation, err, nil) |
|
| 451 | 451 |
} |
| 452 | 452 |
process.stdin = pipes[0] |
| 453 | 453 |
process.stdout = pipes[1] |
| ... | ... |
@@ -455,7 +455,7 @@ func (computeSystem *System) CreateProcess(ctx context.Context, c interface{}) (
|
| 455 | 455 |
process.hasCachedStdio = true |
| 456 | 456 |
|
| 457 | 457 |
if err = process.registerCallback(ctx); err != nil {
|
| 458 |
- return nil, makeSystemError(computeSystem, operation, "", err, nil) |
|
| 458 |
+ return nil, makeSystemError(computeSystem, operation, err, nil) |
|
| 459 | 459 |
} |
| 460 | 460 |
go process.waitBackground() |
| 461 | 461 |
|
| ... | ... |
@@ -470,18 +470,18 @@ func (computeSystem *System) OpenProcess(ctx context.Context, pid int) (*Process |
| 470 | 470 |
operation := "hcsshim::System::OpenProcess" |
| 471 | 471 |
|
| 472 | 472 |
if computeSystem.handle == 0 {
|
| 473 |
- return nil, makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) |
|
| 473 |
+ return nil, makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil) |
|
| 474 | 474 |
} |
| 475 | 475 |
|
| 476 | 476 |
processHandle, resultJSON, err := vmcompute.HcsOpenProcess(ctx, computeSystem.handle, uint32(pid)) |
| 477 | 477 |
events := processHcsResult(ctx, resultJSON) |
| 478 | 478 |
if err != nil {
|
| 479 |
- return nil, makeSystemError(computeSystem, operation, "", err, events) |
|
| 479 |
+ return nil, makeSystemError(computeSystem, operation, err, events) |
|
| 480 | 480 |
} |
| 481 | 481 |
|
| 482 | 482 |
process := newProcess(processHandle, pid, computeSystem) |
| 483 | 483 |
if err = process.registerCallback(ctx); err != nil {
|
| 484 |
- return nil, makeSystemError(computeSystem, operation, "", err, nil) |
|
| 484 |
+ return nil, makeSystemError(computeSystem, operation, err, nil) |
|
| 485 | 485 |
} |
| 486 | 486 |
go process.waitBackground() |
| 487 | 487 |
|
| ... | ... |
@@ -505,12 +505,12 @@ func (computeSystem *System) Close() (err error) {
|
| 505 | 505 |
} |
| 506 | 506 |
|
| 507 | 507 |
if err = computeSystem.unregisterCallback(ctx); err != nil {
|
| 508 |
- return makeSystemError(computeSystem, operation, "", err, nil) |
|
| 508 |
+ return makeSystemError(computeSystem, operation, err, nil) |
|
| 509 | 509 |
} |
| 510 | 510 |
|
| 511 | 511 |
err = vmcompute.HcsCloseComputeSystem(ctx, computeSystem.handle) |
| 512 | 512 |
if err != nil {
|
| 513 |
- return makeSystemError(computeSystem, operation, "", err, nil) |
|
| 513 |
+ return makeSystemError(computeSystem, operation, err, nil) |
|
| 514 | 514 |
} |
| 515 | 515 |
|
| 516 | 516 |
computeSystem.handle = 0 |
| ... | ... |
@@ -587,7 +587,7 @@ func (computeSystem *System) Modify(ctx context.Context, config interface{}) err
|
| 587 | 587 |
operation := "hcsshim::System::Modify" |
| 588 | 588 |
|
| 589 | 589 |
if computeSystem.handle == 0 {
|
| 590 |
- return makeSystemError(computeSystem, operation, "", ErrAlreadyClosed, nil) |
|
| 590 |
+ return makeSystemError(computeSystem, operation, ErrAlreadyClosed, nil) |
|
| 591 | 591 |
} |
| 592 | 592 |
|
| 593 | 593 |
requestBytes, err := json.Marshal(config) |
| ... | ... |
@@ -599,7 +599,7 @@ func (computeSystem *System) Modify(ctx context.Context, config interface{}) err
|
| 599 | 599 |
resultJSON, err := vmcompute.HcsModifyComputeSystem(ctx, computeSystem.handle, requestJSON) |
| 600 | 600 |
events := processHcsResult(ctx, resultJSON) |
| 601 | 601 |
if err != nil {
|
| 602 |
- return makeSystemError(computeSystem, operation, requestJSON, err, events) |
|
| 602 |
+ return makeSystemError(computeSystem, operation, err, events) |
|
| 603 | 603 |
} |
| 604 | 604 |
|
| 605 | 605 |
return nil |