use of com.oracle.svm.core.annotate.Uninterruptible in project graal by oracle.
the class PosixJavaLangSubstitutions method uninterruptibleForkAndExec.
@Uninterruptible(reason = "fragile state after fork()")
private static int uninterruptibleForkAndExec(CCharPointer file, CCharPointer dir, CCharPointerPointer argv, CCharPointerPointer envp, int[] stdioFds, int initialFailFd, PointerBase buffer, int buflen, CCharPointer procFdsPath, CCharPointer searchPaths, CCharPointer searchPathSeparator) {
int childPid;
childPid = UnistdNoTransitions.fork();
if (childPid != 0) {
return childPid;
}
// If we are here, we are the child process.
int failFd = initialFailFd;
try {
// In case of an error, we "return" to end up in the finally block below and notify the
// parent process of the failure.
final int gotoFinally = -1;
if (Java_lang_UNIXProcess_Supplement.dup2(stdioFds[0], 0) < 0) {
return gotoFinally;
}
if (Java_lang_UNIXProcess_Supplement.dup2(stdioFds[1], 1) < 0) {
return gotoFinally;
}
if (Java_lang_UNIXProcess_Supplement.dup2(stdioFds[2], 2) < 0) {
return gotoFinally;
}
if (Java_lang_UNIXProcess_Supplement.dup2(failFd, 3) < 0) {
return gotoFinally;
}
failFd = 3;
// FD_CLOEXEC: close fail pipe on exec() to indicate success to parent
if (Fcntl.fcntl_no_transition(failFd, Fcntl.F_SETFD(), Fcntl.FD_CLOEXEC()) < 0) {
return gotoFinally;
}
/*
* opendir() below allocates a file descriptor. We close failFd+1 so it should become
* the descriptor allocated to opendir() and we can avoid closing it together with the
* other descriptors.
*/
final int maxFd = failFd + 1;
if (UnistdNoTransitions.close(maxFd) < 0) {
return gotoFinally;
}
if (procFdsPath.isNull()) {
// We have no procfs, resort to close file descriptors by trial and error
int maxOpenFds = (int) UnistdNoTransitions.sysconf(Unistd._SC_OPEN_MAX());
for (int fd = maxFd + 1; fd < maxOpenFds; fd++) {
if (UnistdNoTransitions.close(fd) != 0 && Errno.errno() != Errno.EBADF()) {
return gotoFinally;
}
}
} else {
DIR fddir = Dirent.opendir_no_transition(procFdsPath);
if (fddir.isNull()) {
return gotoFinally;
}
dirent dirent = WordFactory.pointer(buffer.rawValue());
direntPointer direntptr = StackValue.get(SizeOf.get(direntPointer.class));
int status;
while ((status = Dirent.readdir_r_no_transition(fddir, dirent, direntptr)) == 0 && direntptr.read().isNonNull()) {
CCharPointerPointer endptr = StackValue.get(SizeOf.get(CCharPointerPointer.class));
long fd = LibC.strtol(dirent.d_name(), endptr, 10);
if (fd > maxFd && endptr.read().isNonNull() && endptr.read().read() == '\0') {
UnistdNoTransitions.close((int) fd);
}
}
if (status != 0) {
// readdir_r() does not set errno
Errno.set_errno(status);
return gotoFinally;
}
Dirent.closedir_no_transition(fddir);
}
if (dir.isNonNull()) {
if (UnistdNoTransitions.chdir(dir) < 0) {
return gotoFinally;
}
}
CCharPointerPointer actualEnvp = envp;
if (actualEnvp.isNull()) {
actualEnvp = LibCHelper.getEnviron();
}
if (LibC.strchr(file, '/').isNonNull()) {
UnistdNoTransitions.execve(argv.read(0), argv, actualEnvp);
} else {
// Scan PATH for the file to execute. We cannot use execvpe()
// because it is a GNU extension that is not universally available.
final int fileStrlen = (int) LibC.strlen(file).rawValue();
int stickyErrno = 0;
final CCharPointerPointer saveptr = StackValue.get(SizeOf.get(CCharPointerPointer.class));
saveptr.write(WordFactory.nullPointer());
CCharPointer searchDir = LibC.strtok_r(searchPaths, searchPathSeparator, saveptr);
while (searchDir.isNonNull()) {
CCharPointer bufptr = WordFactory.pointer(buffer.rawValue());
int len0 = (int) LibC.strlen(searchDir).rawValue();
if (len0 + fileStrlen + 2 > buflen) {
Errno.set_errno(Errno.ENAMETOOLONG());
continue;
}
if (len0 > 0) {
LibC.strcpy(bufptr, searchDir);
if (bufptr.read(len0 - 1) != '/') {
bufptr.write(len0, (byte) '/');
len0++;
}
}
LibC.strcpy(bufptr.addressOf(len0), file);
UnistdNoTransitions.execve(bufptr, argv, actualEnvp);
int e = Errno.errno();
if (e == Errno.EACCES()) {
// as exec(): report EACCES unless we succeed later
stickyErrno = e;
} else if (e == Errno.ENOENT() || e == Errno.ENOTDIR() || e == Errno.ELOOP() || e == Errno.ESTALE() || e == Errno.ENODEV() || e == Errno.ETIMEDOUT()) {
// ignore
} else {
stickyErrno = e;
// bad
break;
}
searchDir = LibC.strtok_r(WordFactory.nullPointer(), searchPathSeparator, saveptr);
}
if (stickyErrno != 0) {
Errno.set_errno(stickyErrno);
}
}
// If we are here, exec certainly failed.
} catch (Throwable t) {
Errno.set_errno(Integer.MIN_VALUE);
} finally {
try {
// notify parent of failure
final int intSize = SizeOf.get(CIntPointer.class);
CIntPointer pErrno = StackValue.get(intSize);
pErrno.write(Errno.errno());
Java_lang_UNIXProcess_Supplement.writeEntirely(failFd, pErrno, WordFactory.unsigned(intSize));
UnistdNoTransitions.close(failFd);
} finally {
UnistdNoTransitions._exit(-1);
}
}
throw VMError.shouldNotReachHere();
}
use of com.oracle.svm.core.annotate.Uninterruptible in project graal by oracle.
the class PosixCEntryPointSnippets method failFatally.
@Uninterruptible(reason = "Unknown thread state.")
@SubstrateForeignCallTarget
private static void failFatally(int code, CCharPointer message) {
FILE stderr = fdopen(2, FAIL_FATALLY_FDOPEN_MODE.get());
fprintfSD(stderr, FAIL_FATALLY_MESSAGE_FORMAT.get(), message, code);
LibC.exit(code);
}
use of com.oracle.svm.core.annotate.Uninterruptible in project graal by oracle.
the class PosixCEntryPointSnippets method createIsolate.
@Uninterruptible(reason = "Thread state not yet set up.")
@SubstrateForeignCallTarget
private static int createIsolate(CEntryPointCreateIsolateParameters parameters, int vmThreadSize) {
WordPointer isolate = StackValue.get(SizeOf.get(WordPointer.class));
isolate.write(Word.nullPointer());
int error = PosixIsolates.create(isolate, parameters);
if (error != Errors.NO_ERROR) {
return error;
}
if (UseHeapBaseRegister.getValue()) {
setHeapBase(PosixIsolates.getHeapBase(isolate.read()));
}
if (MultiThreaded.getValue()) {
PosixVMThreads.ensureInitialized();
}
return attachThread(isolate.read(), vmThreadSize);
}
use of com.oracle.svm.core.annotate.Uninterruptible in project graal by oracle.
the class PosixCEntryPointSnippets method attachThread.
@Uninterruptible(reason = "Thread state not yet set up.")
@SubstrateForeignCallTarget
private static int attachThread(Isolate isolate, int vmThreadSize) {
int sanityError = PosixIsolates.checkSanity(isolate);
if (sanityError != Errors.NO_ERROR) {
return sanityError;
}
if (UseHeapBaseRegister.getValue()) {
setHeapBase(PosixIsolates.getHeapBase(isolate));
}
if (MultiThreaded.getValue()) {
if (!PosixVMThreads.isInitialized()) {
return Errors.UNINITIALIZED_ISOLATE;
}
IsolateThread thread = PosixVMThreads.VMThreadTL.get();
if (VMThreads.isNullThread(thread)) {
// not attached
thread = LibC.calloc(WordFactory.unsigned(1), WordFactory.unsigned(vmThreadSize));
VMThreads.attachThread(thread);
// Store thread and isolate in thread-local variables.
PosixVMThreads.VMThreadTL.set(thread);
PosixVMThreads.IsolateTL.set(thread, isolate);
}
writeCurrentVMThread(thread);
}
return Errors.NO_ERROR;
}
use of com.oracle.svm.core.annotate.Uninterruptible in project graal by oracle.
the class PosixCEntryPointSnippets method detachThreadMT.
@SubstrateForeignCallTarget
@Uninterruptible(reason = "Thread state going away.")
@RestrictHeapAccess(access = RestrictHeapAccess.Access.NO_ALLOCATION, reason = "Must not (thread-local) allocate while detaching a thread.")
private static int detachThreadMT(IsolateThread thread) {
int result = Errors.NO_ERROR;
/*
* Set thread status to exited. This makes me immune to safepoints (the safepoint mechanism
* ignores me). Also clear any pending safepoint requests, since I will not honor them.
*/
VMThreads.StatusSupport.setStatusExited();
Safepoint.setSafepointRequested(Safepoint.SafepointRequestValues.RESET);
// try-finally because try-with-resources can call interruptible code
VMThreads.THREAD_MUTEX.lockNoTransition();
try {
detachJavaLangThreadMT(thread);
// clear references to thread to avoid unintended use
writeCurrentVMThread(VMThreads.nullThread());
PosixVMThreads.VMThreadTL.set(VMThreads.nullThread());
VMThreads.detachThread(thread);
} catch (Throwable t) {
result = Errors.UNSPECIFIED;
} finally {
VMThreads.THREAD_MUTEX.unlock();
LibC.free(thread);
}
return result;
}
Aggregations