1
2
3 package vmcompute
4
5 import (
6 gcontext "context"
7 "syscall"
8 "time"
9
10 "github.com/sirupsen/logrus"
11 "go.opencensus.io/trace"
12
13 "github.com/Microsoft/hcsshim/internal/interop"
14 "github.com/Microsoft/hcsshim/internal/log"
15 "github.com/Microsoft/hcsshim/internal/logfields"
16 "github.com/Microsoft/hcsshim/internal/oc"
17 "github.com/Microsoft/hcsshim/internal/timeout"
18 )
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51 const errVmcomputeOperationPending = syscall.Errno(0xC0370103)
52
53
54 type HcsSystem syscall.Handle
55
56
57
58 type HcsProcess syscall.Handle
59
60
61
62 type HcsCallback syscall.Handle
63
64
65
66 type HcsProcessInformation struct {
67
68 ProcessId uint32
69 _ uint32
70
71 StdInput syscall.Handle
72
73 StdOutput syscall.Handle
74
75 StdError syscall.Handle
76 }
77
78 func execute(ctx gcontext.Context, timeout time.Duration, f func() error) error {
79 now := time.Now()
80 if timeout > 0 {
81 var cancel gcontext.CancelFunc
82 ctx, cancel = gcontext.WithTimeout(ctx, timeout)
83 defer cancel()
84 }
85
86
87
88
89
90
91 deadline, ok := ctx.Deadline()
92 trueTimeout := timeout
93 if ok {
94 trueTimeout = deadline.Sub(now)
95 log.G(ctx).WithFields(logrus.Fields{
96 logfields.Timeout: trueTimeout,
97 "desiredTimeout": timeout,
98 }).Trace("Executing syscall with deadline")
99 }
100
101 done := make(chan error, 1)
102 go func() {
103 done <- f()
104 }()
105 select {
106 case <-ctx.Done():
107 if ctx.Err() == gcontext.DeadlineExceeded {
108 log.G(ctx).WithField(logfields.Timeout, trueTimeout).
109 Warning("Syscall did not complete within operation timeout. This may indicate a platform issue. " +
110 "If it appears to be making no forward progress, obtain the stacks and see if there is a syscall " +
111 "stuck in the platform API for a significant length of time.")
112 }
113 return ctx.Err()
114 case err := <-done:
115 return err
116 }
117 }
118
119 func HcsEnumerateComputeSystems(ctx gcontext.Context, query string) (computeSystems, result string, hr error) {
120 ctx, span := oc.StartSpan(ctx, "HcsEnumerateComputeSystems")
121 defer span.End()
122 defer func() {
123 if result != "" {
124 span.AddAttributes(trace.StringAttribute("result", result))
125 }
126 oc.SetSpanStatus(span, hr)
127 }()
128 span.AddAttributes(trace.StringAttribute("query", query))
129
130 return computeSystems, result, execute(ctx, timeout.SyscallWatcher, func() error {
131 var (
132 computeSystemsp *uint16
133 resultp *uint16
134 )
135 err := hcsEnumerateComputeSystems(query, &computeSystemsp, &resultp)
136 if computeSystemsp != nil {
137 computeSystems = interop.ConvertAndFreeCoTaskMemString(computeSystemsp)
138 }
139 if resultp != nil {
140 result = interop.ConvertAndFreeCoTaskMemString(resultp)
141 }
142 return err
143 })
144 }
145
146 func HcsCreateComputeSystem(ctx gcontext.Context, id string, configuration string, identity syscall.Handle) (computeSystem HcsSystem, result string, hr error) {
147 ctx, span := oc.StartSpan(ctx, "HcsCreateComputeSystem")
148 defer span.End()
149 defer func() {
150 if result != "" {
151 span.AddAttributes(trace.StringAttribute("result", result))
152 }
153 if hr != errVmcomputeOperationPending {
154 oc.SetSpanStatus(span, hr)
155 }
156 }()
157 span.AddAttributes(
158 trace.StringAttribute("id", id),
159 trace.StringAttribute("configuration", configuration))
160
161 return computeSystem, result, execute(ctx, timeout.SystemCreate, func() error {
162 var resultp *uint16
163 err := hcsCreateComputeSystem(id, configuration, identity, &computeSystem, &resultp)
164 if resultp != nil {
165 result = interop.ConvertAndFreeCoTaskMemString(resultp)
166 }
167 return err
168 })
169 }
170
171 func HcsOpenComputeSystem(ctx gcontext.Context, id string) (computeSystem HcsSystem, result string, hr error) {
172 ctx, span := oc.StartSpan(ctx, "HcsOpenComputeSystem")
173 defer span.End()
174 defer func() {
175 if result != "" {
176 span.AddAttributes(trace.StringAttribute("result", result))
177 }
178 oc.SetSpanStatus(span, hr)
179 }()
180
181 return computeSystem, result, execute(ctx, timeout.SyscallWatcher, func() error {
182 var resultp *uint16
183 err := hcsOpenComputeSystem(id, &computeSystem, &resultp)
184 if resultp != nil {
185 result = interop.ConvertAndFreeCoTaskMemString(resultp)
186 }
187 return err
188 })
189 }
190
191 func HcsCloseComputeSystem(ctx gcontext.Context, computeSystem HcsSystem) (hr error) {
192 ctx, span := oc.StartSpan(ctx, "HcsCloseComputeSystem")
193 defer span.End()
194 defer func() { oc.SetSpanStatus(span, hr) }()
195
196 return execute(ctx, timeout.SyscallWatcher, func() error {
197 return hcsCloseComputeSystem(computeSystem)
198 })
199 }
200
201 func HcsStartComputeSystem(ctx gcontext.Context, computeSystem HcsSystem, options string) (result string, hr error) {
202 ctx, span := oc.StartSpan(ctx, "HcsStartComputeSystem")
203 defer span.End()
204 defer func() {
205 if result != "" {
206 span.AddAttributes(trace.StringAttribute("result", result))
207 }
208 if hr != errVmcomputeOperationPending {
209 oc.SetSpanStatus(span, hr)
210 }
211 }()
212 span.AddAttributes(trace.StringAttribute("options", options))
213
214 return result, execute(ctx, timeout.SystemStart, func() error {
215 var resultp *uint16
216 err := hcsStartComputeSystem(computeSystem, options, &resultp)
217 if resultp != nil {
218 result = interop.ConvertAndFreeCoTaskMemString(resultp)
219 }
220 return err
221 })
222 }
223
224 func HcsShutdownComputeSystem(ctx gcontext.Context, computeSystem HcsSystem, options string) (result string, hr error) {
225 ctx, span := oc.StartSpan(ctx, "HcsShutdownComputeSystem")
226 defer span.End()
227 defer func() {
228 if result != "" {
229 span.AddAttributes(trace.StringAttribute("result", result))
230 }
231 if hr != errVmcomputeOperationPending {
232 oc.SetSpanStatus(span, hr)
233 }
234 }()
235 span.AddAttributes(trace.StringAttribute("options", options))
236
237 return result, execute(ctx, timeout.SyscallWatcher, func() error {
238 var resultp *uint16
239 err := hcsShutdownComputeSystem(computeSystem, options, &resultp)
240 if resultp != nil {
241 result = interop.ConvertAndFreeCoTaskMemString(resultp)
242 }
243 return err
244 })
245 }
246
247 func HcsTerminateComputeSystem(ctx gcontext.Context, computeSystem HcsSystem, options string) (result string, hr error) {
248 ctx, span := oc.StartSpan(ctx, "HcsTerminateComputeSystem")
249 defer span.End()
250 defer func() {
251 if result != "" {
252 span.AddAttributes(trace.StringAttribute("result", result))
253 }
254 if hr != errVmcomputeOperationPending {
255 oc.SetSpanStatus(span, hr)
256 }
257 }()
258 span.AddAttributes(trace.StringAttribute("options", options))
259
260 return result, execute(ctx, timeout.SyscallWatcher, func() error {
261 var resultp *uint16
262 err := hcsTerminateComputeSystem(computeSystem, options, &resultp)
263 if resultp != nil {
264 result = interop.ConvertAndFreeCoTaskMemString(resultp)
265 }
266 return err
267 })
268 }
269
270 func HcsPauseComputeSystem(ctx gcontext.Context, computeSystem HcsSystem, options string) (result string, hr error) {
271 ctx, span := oc.StartSpan(ctx, "HcsPauseComputeSystem")
272 defer span.End()
273 defer func() {
274 if result != "" {
275 span.AddAttributes(trace.StringAttribute("result", result))
276 }
277 if hr != errVmcomputeOperationPending {
278 oc.SetSpanStatus(span, hr)
279 }
280 }()
281 span.AddAttributes(trace.StringAttribute("options", options))
282
283 return result, execute(ctx, timeout.SystemPause, func() error {
284 var resultp *uint16
285 err := hcsPauseComputeSystem(computeSystem, options, &resultp)
286 if resultp != nil {
287 result = interop.ConvertAndFreeCoTaskMemString(resultp)
288 }
289 return err
290 })
291 }
292
293 func HcsResumeComputeSystem(ctx gcontext.Context, computeSystem HcsSystem, options string) (result string, hr error) {
294 ctx, span := oc.StartSpan(ctx, "HcsResumeComputeSystem")
295 defer span.End()
296 defer func() {
297 if result != "" {
298 span.AddAttributes(trace.StringAttribute("result", result))
299 }
300 if hr != errVmcomputeOperationPending {
301 oc.SetSpanStatus(span, hr)
302 }
303 }()
304 span.AddAttributes(trace.StringAttribute("options", options))
305
306 return result, execute(ctx, timeout.SystemResume, func() error {
307 var resultp *uint16
308 err := hcsResumeComputeSystem(computeSystem, options, &resultp)
309 if resultp != nil {
310 result = interop.ConvertAndFreeCoTaskMemString(resultp)
311 }
312 return err
313 })
314 }
315
316 func HcsGetComputeSystemProperties(ctx gcontext.Context, computeSystem HcsSystem, propertyQuery string) (properties, result string, hr error) {
317 ctx, span := oc.StartSpan(ctx, "HcsGetComputeSystemProperties")
318 defer span.End()
319 defer func() {
320 if result != "" {
321 span.AddAttributes(trace.StringAttribute("result", result))
322 }
323 oc.SetSpanStatus(span, hr)
324 }()
325 span.AddAttributes(trace.StringAttribute("propertyQuery", propertyQuery))
326
327 return properties, result, execute(ctx, timeout.SyscallWatcher, func() error {
328 var (
329 propertiesp *uint16
330 resultp *uint16
331 )
332 err := hcsGetComputeSystemProperties(computeSystem, propertyQuery, &propertiesp, &resultp)
333 if propertiesp != nil {
334 properties = interop.ConvertAndFreeCoTaskMemString(propertiesp)
335 }
336 if resultp != nil {
337 result = interop.ConvertAndFreeCoTaskMemString(resultp)
338 }
339 return err
340 })
341 }
342
343 func HcsModifyComputeSystem(ctx gcontext.Context, computeSystem HcsSystem, configuration string) (result string, hr error) {
344 ctx, span := oc.StartSpan(ctx, "HcsModifyComputeSystem")
345 defer span.End()
346 defer func() {
347 if result != "" {
348 span.AddAttributes(trace.StringAttribute("result", result))
349 }
350 oc.SetSpanStatus(span, hr)
351 }()
352 span.AddAttributes(trace.StringAttribute("configuration", configuration))
353
354 return result, execute(ctx, timeout.SyscallWatcher, func() error {
355 var resultp *uint16
356 err := hcsModifyComputeSystem(computeSystem, configuration, &resultp)
357 if resultp != nil {
358 result = interop.ConvertAndFreeCoTaskMemString(resultp)
359 }
360 return err
361 })
362 }
363
364 func HcsModifyServiceSettings(ctx gcontext.Context, settings string) (result string, hr error) {
365 ctx, span := oc.StartSpan(ctx, "HcsModifyServiceSettings")
366 defer span.End()
367 defer func() {
368 if result != "" {
369 span.AddAttributes(trace.StringAttribute("result", result))
370 }
371 oc.SetSpanStatus(span, hr)
372 }()
373 span.AddAttributes(trace.StringAttribute("settings", settings))
374
375 return result, execute(ctx, timeout.SyscallWatcher, func() error {
376 var resultp *uint16
377 err := hcsModifyServiceSettings(settings, &resultp)
378 if resultp != nil {
379 result = interop.ConvertAndFreeCoTaskMemString(resultp)
380 }
381 return err
382 })
383 }
384
385 func HcsRegisterComputeSystemCallback(ctx gcontext.Context, computeSystem HcsSystem, callback uintptr, context uintptr) (callbackHandle HcsCallback, hr error) {
386 ctx, span := oc.StartSpan(ctx, "HcsRegisterComputeSystemCallback")
387 defer span.End()
388 defer func() { oc.SetSpanStatus(span, hr) }()
389
390 return callbackHandle, execute(ctx, timeout.SyscallWatcher, func() error {
391 return hcsRegisterComputeSystemCallback(computeSystem, callback, context, &callbackHandle)
392 })
393 }
394
395 func HcsUnregisterComputeSystemCallback(ctx gcontext.Context, callbackHandle HcsCallback) (hr error) {
396 ctx, span := oc.StartSpan(ctx, "HcsUnregisterComputeSystemCallback")
397 defer span.End()
398 defer func() { oc.SetSpanStatus(span, hr) }()
399
400 return execute(ctx, timeout.SyscallWatcher, func() error {
401 return hcsUnregisterComputeSystemCallback(callbackHandle)
402 })
403 }
404
405 func HcsCreateProcess(ctx gcontext.Context, computeSystem HcsSystem, processParameters string) (processInformation HcsProcessInformation, process HcsProcess, result string, hr error) {
406 ctx, span := oc.StartSpan(ctx, "HcsCreateProcess")
407 defer span.End()
408 defer func() {
409 if result != "" {
410 span.AddAttributes(trace.StringAttribute("result", result))
411 }
412 oc.SetSpanStatus(span, hr)
413 }()
414 if span.IsRecordingEvents() {
415
416 if s, err := log.ScrubProcessParameters(processParameters); err == nil {
417 span.AddAttributes(trace.StringAttribute("processParameters", s))
418 }
419 }
420
421 return processInformation, process, result, execute(ctx, timeout.SyscallWatcher, func() error {
422 var resultp *uint16
423 err := hcsCreateProcess(computeSystem, processParameters, &processInformation, &process, &resultp)
424 if resultp != nil {
425 result = interop.ConvertAndFreeCoTaskMemString(resultp)
426 }
427 return err
428 })
429 }
430
431 func HcsOpenProcess(ctx gcontext.Context, computeSystem HcsSystem, pid uint32) (process HcsProcess, result string, hr error) {
432 ctx, span := oc.StartSpan(ctx, "HcsOpenProcess")
433 defer span.End()
434 defer func() {
435 if result != "" {
436 span.AddAttributes(trace.StringAttribute("result", result))
437 }
438 oc.SetSpanStatus(span, hr)
439 }()
440 span.AddAttributes(trace.Int64Attribute("pid", int64(pid)))
441
442 return process, result, execute(ctx, timeout.SyscallWatcher, func() error {
443 var resultp *uint16
444 err := hcsOpenProcess(computeSystem, pid, &process, &resultp)
445 if resultp != nil {
446 result = interop.ConvertAndFreeCoTaskMemString(resultp)
447 }
448 return err
449 })
450 }
451
452 func HcsCloseProcess(ctx gcontext.Context, process HcsProcess) (hr error) {
453 ctx, span := oc.StartSpan(ctx, "HcsCloseProcess")
454 defer span.End()
455 defer func() { oc.SetSpanStatus(span, hr) }()
456
457 return execute(ctx, timeout.SyscallWatcher, func() error {
458 return hcsCloseProcess(process)
459 })
460 }
461
462 func HcsTerminateProcess(ctx gcontext.Context, process HcsProcess) (result string, hr error) {
463 ctx, span := oc.StartSpan(ctx, "HcsTerminateProcess")
464 defer span.End()
465 defer func() {
466 if result != "" {
467 span.AddAttributes(trace.StringAttribute("result", result))
468 }
469 oc.SetSpanStatus(span, hr)
470 }()
471
472 return result, execute(ctx, timeout.SyscallWatcher, func() error {
473 var resultp *uint16
474 err := hcsTerminateProcess(process, &resultp)
475 if resultp != nil {
476 result = interop.ConvertAndFreeCoTaskMemString(resultp)
477 }
478 return err
479 })
480 }
481
482 func HcsSignalProcess(ctx gcontext.Context, process HcsProcess, options string) (result string, hr error) {
483 ctx, span := oc.StartSpan(ctx, "HcsSignalProcess")
484 defer span.End()
485 defer func() {
486 if result != "" {
487 span.AddAttributes(trace.StringAttribute("result", result))
488 }
489 oc.SetSpanStatus(span, hr)
490 }()
491 span.AddAttributes(trace.StringAttribute("options", options))
492
493 return result, execute(ctx, timeout.SyscallWatcher, func() error {
494 var resultp *uint16
495 err := hcsSignalProcess(process, options, &resultp)
496 if resultp != nil {
497 result = interop.ConvertAndFreeCoTaskMemString(resultp)
498 }
499 return err
500 })
501 }
502
503 func HcsGetProcessInfo(ctx gcontext.Context, process HcsProcess) (processInformation HcsProcessInformation, result string, hr error) {
504 ctx, span := oc.StartSpan(ctx, "HcsGetProcessInfo")
505 defer span.End()
506 defer func() {
507 if result != "" {
508 span.AddAttributes(trace.StringAttribute("result", result))
509 }
510 oc.SetSpanStatus(span, hr)
511 }()
512
513 return processInformation, result, execute(ctx, timeout.SyscallWatcher, func() error {
514 var resultp *uint16
515 err := hcsGetProcessInfo(process, &processInformation, &resultp)
516 if resultp != nil {
517 result = interop.ConvertAndFreeCoTaskMemString(resultp)
518 }
519 return err
520 })
521 }
522
523 func HcsGetProcessProperties(ctx gcontext.Context, process HcsProcess) (processProperties, result string, hr error) {
524 ctx, span := oc.StartSpan(ctx, "HcsGetProcessProperties")
525 defer span.End()
526 defer func() {
527 if result != "" {
528 span.AddAttributes(trace.StringAttribute("result", result))
529 }
530 oc.SetSpanStatus(span, hr)
531 }()
532
533 return processProperties, result, execute(ctx, timeout.SyscallWatcher, func() error {
534 var (
535 processPropertiesp *uint16
536 resultp *uint16
537 )
538 err := hcsGetProcessProperties(process, &processPropertiesp, &resultp)
539 if processPropertiesp != nil {
540 processProperties = interop.ConvertAndFreeCoTaskMemString(processPropertiesp)
541 }
542 if resultp != nil {
543 result = interop.ConvertAndFreeCoTaskMemString(resultp)
544 }
545 return err
546 })
547 }
548
549 func HcsModifyProcess(ctx gcontext.Context, process HcsProcess, settings string) (result string, hr error) {
550 ctx, span := oc.StartSpan(ctx, "HcsModifyProcess")
551 defer span.End()
552 defer func() {
553 if result != "" {
554 span.AddAttributes(trace.StringAttribute("result", result))
555 }
556 oc.SetSpanStatus(span, hr)
557 }()
558 span.AddAttributes(trace.StringAttribute("settings", settings))
559
560 return result, execute(ctx, timeout.SyscallWatcher, func() error {
561 var resultp *uint16
562 err := hcsModifyProcess(process, settings, &resultp)
563 if resultp != nil {
564 result = interop.ConvertAndFreeCoTaskMemString(resultp)
565 }
566 return err
567 })
568 }
569
570 func HcsGetServiceProperties(ctx gcontext.Context, propertyQuery string) (properties, result string, hr error) {
571 ctx, span := oc.StartSpan(ctx, "HcsGetServiceProperties")
572 defer span.End()
573 defer func() {
574 if result != "" {
575 span.AddAttributes(trace.StringAttribute("result", result))
576 }
577 oc.SetSpanStatus(span, hr)
578 }()
579 span.AddAttributes(trace.StringAttribute("propertyQuery", propertyQuery))
580
581 return properties, result, execute(ctx, timeout.SyscallWatcher, func() error {
582 var (
583 propertiesp *uint16
584 resultp *uint16
585 )
586 err := hcsGetServiceProperties(propertyQuery, &propertiesp, &resultp)
587 if propertiesp != nil {
588 properties = interop.ConvertAndFreeCoTaskMemString(propertiesp)
589 }
590 if resultp != nil {
591 result = interop.ConvertAndFreeCoTaskMemString(resultp)
592 }
593 return err
594 })
595 }
596
597 func HcsRegisterProcessCallback(ctx gcontext.Context, process HcsProcess, callback uintptr, context uintptr) (callbackHandle HcsCallback, hr error) {
598 ctx, span := oc.StartSpan(ctx, "HcsRegisterProcessCallback")
599 defer span.End()
600 defer func() { oc.SetSpanStatus(span, hr) }()
601
602 return callbackHandle, execute(ctx, timeout.SyscallWatcher, func() error {
603 return hcsRegisterProcessCallback(process, callback, context, &callbackHandle)
604 })
605 }
606
607 func HcsUnregisterProcessCallback(ctx gcontext.Context, callbackHandle HcsCallback) (hr error) {
608 ctx, span := oc.StartSpan(ctx, "HcsUnregisterProcessCallback")
609 defer span.End()
610 defer func() { oc.SetSpanStatus(span, hr) }()
611
612 return execute(ctx, timeout.SyscallWatcher, func() error {
613 return hcsUnregisterProcessCallback(callbackHandle)
614 })
615 }
616
617 func HcsSaveComputeSystem(ctx gcontext.Context, computeSystem HcsSystem, options string) (result string, hr error) {
618 ctx, span := oc.StartSpan(ctx, "HcsSaveComputeSystem")
619 defer span.End()
620 defer func() {
621 if result != "" {
622 span.AddAttributes(trace.StringAttribute("result", result))
623 }
624 if hr != errVmcomputeOperationPending {
625 oc.SetSpanStatus(span, hr)
626 }
627 }()
628
629 return result, execute(ctx, timeout.SyscallWatcher, func() error {
630 var resultp *uint16
631 err := hcsSaveComputeSystem(computeSystem, options, &resultp)
632 if resultp != nil {
633 result = interop.ConvertAndFreeCoTaskMemString(resultp)
634 }
635 return err
636 })
637 }
638
View as plain text