File: ExecSandbox.m

package info (click to toggle)
julia 1.5.3%2Bdfsg-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 91,132 kB
  • sloc: lisp: 278,486; ansic: 60,186; cpp: 29,801; sh: 2,403; makefile: 1,998; pascal: 1,313; objc: 647; javascript: 516; asm: 226; python: 161; xml: 34
file content (149 lines) | stat: -rw-r--r-- 4,079 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
// This file is a part of Julia. License is MIT: https://julialang.org/license

#import "ExecSandbox.h"

@class JuliaTask;

@interface ExecSandbox () {
  NSMutableArray<JuliaTask *> *_Nonnull _tasks;
}
- (void)taskTerminated:(JuliaTask *_Nonnull)jt;
@end

@interface JuliaTask : NSObject <TaskProtocol> {
  ExecSandbox *__weak _delegate;
  dispatch_block_t _Nullable _onCleanup;
  NSTask *_Nonnull _task;
}
@end

@implementation JuliaTask

- (instancetype)initWithTask:(NSTask *_Nonnull)task
                    delegate:(ExecSandbox *)d
                     cleanup:(dispatch_block_t)onCleanup {
  self = [super init];
  if (self == nil) {
    return nil;
  }
  _delegate = d;
  _onCleanup = onCleanup;
  _task = task;
  return self;
}

- (void)launch:(void (^_Nullable)(int status))onTermination {
  dispatch_block_t onCleanup = _onCleanup;
  JuliaTask __weak *weakSelf = self;
  _task.terminationHandler = ^(NSTask *_Nonnull t) {
    if (onTermination != nil) {
      onTermination(t.terminationStatus);
    }
    if (onCleanup != nil) {
      onCleanup();
    }
    JuliaTask *strongSelf = weakSelf;
    if (strongSelf) {
      [strongSelf->_delegate taskTerminated:strongSelf];
    }
  };
  @try {
    [_task launch];
  } @catch (NSException *exception) {
    NSLog(@"NSTask launch exception: %@", exception);
  }
}

- (void)terminate {
  @try {
    [_task terminate];
  } @catch (NSException *exception) {
    NSLog(@"NSTask terminate exception: %@", exception);
  }
}

@end

@implementation ExecSandbox

- (instancetype)init {
  self = [super init];
  if (self == nil) {
    return nil;
  }
  _tasks = [[NSMutableArray alloc] init];
  return self;
}

- (void)eval:(NSString *)p
    withJulia:(NSData *)executableBookmark
    arguments:(NSArray<NSString *> *)baseArgs
         task:(void (^)(id<TaskProtocol> task, NSFileHandle *stdIn,
                        NSFileHandle *stdOut, NSFileHandle *stdErr))reply {

  NSURL *executableURL =
      [NSURL URLByResolvingBookmarkData:executableBookmark
                                options:NSURLBookmarkResolutionWithoutUI
                          relativeToURL:nil
                    bookmarkDataIsStale:nil
                                  error:nil];
  if (executableURL == nil) {
    reply(nil, nil, nil, nil);
    return;
  }

  for (NSString *arg in baseArgs) {
    if ([arg isEqual:@"--"]) {
      reply(nil, nil, nil, nil);
      return;
    }
  }

  NSURL *temporaryDirectoryURL = [NSURL fileURLWithPath:NSTemporaryDirectory()
                                            isDirectory:YES];
  NSString *temporaryFilename =
      [[NSProcessInfo processInfo] globallyUniqueString];
  NSURL *temporaryFileURL =
      [temporaryDirectoryURL URLByAppendingPathComponent:temporaryFilename
                                             isDirectory:NO];

  [[p dataUsingEncoding:NSUTF8StringEncoding] writeToURL:temporaryFileURL
                                              atomically:NO];

  NSMutableArray<NSString *> *args = [[NSMutableArray alloc] init];
  [args addObjectsFromArray:baseArgs];
  [args addObjectsFromArray:@[ @"--", temporaryFileURL.path ]];

  NSPipe *stdIn = [NSPipe pipe], *stdOut = [NSPipe pipe],
         *stdErr = [NSPipe pipe];

  NSTask *t = [[NSTask alloc] init];
  if (@available(macOS 10.13, *)) {
    t.executableURL = executableURL;
  } else {
    t.launchPath = executableURL.path;
  }
  t.arguments = args;
  t.standardInput = stdIn;
  t.standardOutput = stdOut;
  t.standardError = stdErr;

  JuliaTask *jt =
      [[JuliaTask alloc] initWithTask:t
                             delegate:self
                              cleanup:^() {
                                [[NSFileManager defaultManager]
                                    removeItemAtURL:temporaryDirectoryURL
                                              error:nil];
                              }];
  [_tasks addObject:jt];

  reply(jt, stdIn.fileHandleForWriting, stdOut.fileHandleForReading,
        stdErr.fileHandleForReading);
}

- (void)taskTerminated:(JuliaTask *_Nonnull)jt {
  [_tasks removeObject:jt];
}

@end