I have a fortran subroutine. It runs quite long time once started.
Now, I want to write a program which calls the fortran subroutine from C++ in a thread.
The thread should be stopped(or canceled) when user requested.
But the subroutine does not support any method to terminate the calculation during it running.
As far as I know, the subroutine uses only stack variables(no allocation).
The subroutine is given by static library for windows(.lib file).
In this case, may I assume that killing the subroutine thread does not causes any problem such as resource leaking?
FYI, here's the running environment:
OS: Windows 7 64bit or above
Compiler: MSVC 2015 for C++, Intel Parallel Studio for fortran
In general it's not safe -- there are other resources that the thread could acquire besides memory. For example, it could lock a mutex, and if you killed the thread while the mutex was locked, the mutex would remain locked forever, with the likely result that other threads would deadlock waiting forever to acquire the mutex. If you really have no way to get the thread to exit cleanly/voluntarily, then the only safe approach is to spawn a child process and run the routine inside the child process. You can safely kill the child process if you have to, because the OS will automatically clean up any resources that were allocated by the child process.
Related
I am taking an OS class and trying to wrap my head around this question, any help would be appreciated:
Consider a multi-threaded process with 10 threads. Thread 3 invokes an execlp() system call. Describe what will happen to each of the threads.
My understanding of exec() is that is replaces the current process with a new one, and it's main difference from fork() is that fork() creates a clone and you end up with duplicates.
So if exec() replaces the current process, would it kill the threads of the old process and replace them with the new one? Any help will be appreciated.
exec()...replaces the current process with a new one.
Actually, it's still the same process after calling exec, and that's important because the parent process may still need to communicate with it, signal it, etc. What exec does is, it guts the process—wipes out all of it's virtual memory, resets all of its signal handlers, unlocks locks, closes some open files, etc. (See here for more)—and then it loads a new program into the existing process and starts executing it.
would it kill the threads of the old process...?
man 2 execve says, "All threads other than the calling thread are destroyed during
an execve(). Mutexes, condition variables, and other pthreads
objects are not preserved."
pthread_detach marks a thread so that when it terminates, its resources are automatically released without requiring the parent thread to call pthread_join. How can it do this? From the perspective of Linux in particular, there are two resources in particular I am curious about:
As an implementation detail, I would expect that if a wait system call is not performed on the terminated thread, then the thread would become a zombie. I assume that the pthread library's solution to this problem does not involve SIGCHLD, because (I think) it still works regardless of what action the program has specified to occur when SIGCHLD is received.
Threads are created using the clone system call. The caller must allocate memory to serve as the child thread's stack area before calling clone. Elsewhere on Stack Overflow, it was recommended that the caller use mmap to allocate the stack for the child. How can the stack be unmapped after the thread exits?
It seems to me that pthread_detach must somehow provide solutions to both of these problems, otherwise, a program that spawns and detaches many threads would eventually lose the ability to continue spawning new threads, even though the detached threads may have terminated already.
The pthreads library (on Linux, NPTL) provides a wrapper around lower-level primitives such as clone(2). When a thread is created with pthread_create, the function passed to clone is a wrapper function. That function allocates the stack and stores that information plus any other metadata into a structure, then calls the user-provided start function. When the user-provided start function returns, cleanup happens. Finally, an internal function called __exit_thread is called to make a system call to exit the thread.
When such a thread is detached, it still returns from the user-provided start function and calls the cleanup code as before, except the stack and metadata is freed as part of this since there is nobody waiting for this thread to complete. This would normally be handled by pthread_join.
If a thread is killed or exits without having run, then the cleanup is handled by the next pthread_create call, which will call any cleanup handlers yet to be run.
The reason a SIGCHLD is not sent to the parent nor is wait(2) required is because the CLONE_THREAD flag to clone(2) is used. The manual page says the following about this flag:
A new thread created with CLONE_THREAD has the same parent process as the process that made the clone call (i.e., like CLONE_PARENT), so that calls to getppid(2) return the same value for all of the threads in a thread group. When a CLONE_THREAD thread terminates, the thread that created it is not sent a SIGCHLD (or other termination) signal; nor can the status of such a thread be obtained using wait(2). (The thread is said to be detached.)
As you noted, this is required for the expected POSIX semantics to occur.
I had a doubt on using fork on a multi-threaded process.
If a process has multiple threads (already created using pthread_create and did a pthread_join) and I call fork, will it copy the same functions assigned to the threads in the child process or create a space where we can reassign the functions?
Read carefully what POSIX says about fork() and threads. In particular:
A process shall be created with a single thread. If a multi-threaded process calls fork(), the new process shall contain a replica of the calling thread and its entire address space, possibly including the states of mutexes and other resources. Consequently, to avoid errors, the child process may only execute async-signal-safe operations until such time as one of the exec functions is called.
The child process will have a single thread running in the context of the calling thread. Other parts of the original process may be tied up by threads that no longer exist (so mutexes may be locked, for example).
The rationale section (further down the linked page) says:
There are two reasons why POSIX programmers call fork(). One reason is to create a new thread of control within the same program (which was originally only possible in POSIX by creating a new process); the other is to create a new process running a different program. In the latter case, the call to fork() is soon followed by a call to one of the exec functions.
The general problem with making fork() work in a multi-threaded world is what to do with all of the threads. There are two alternatives. One is to copy all of the threads into the new process. This causes the programmer or implementation to deal with threads that are suspended on system calls or that might be about to execute system calls that should not be executed in the new process. The other alternative is to copy only the thread that calls fork(). This creates the difficulty that the state of process-local resources is usually held in process memory. If a thread that is not calling fork() holds a resource, that resource is never released in the child process because the thread whose job it is to release the resource does not exist in the child process.
When a programmer is writing a multi-threaded program, the first described use of fork(), creating new threads in the same program, is provided by the pthread_create() function. The fork() function is thus used only to run new programs, and the effects of calling functions that require certain resources between the call to fork() and the call to an exec function are undefined.
What is the difference between exit() and exit_group(). Any process that has multiple threads should use exit_group instead of exit?
To answer the question why do you ask - we are having an process that has around forty threads. When a thread is locked up, we automatically exit the process and then restart the process. And we print the backtrace of the thread that was locked up. We wanted to know whether calling exit in this case is any different from exit_group.
From the docs: This system call is equivalent to exit(2) except that it terminates not only the calling thread, but all threads in the calling process's thread group - However, what is the difference between exiting the process and exiting all the threads. Isn't exiting process == exiting all the threads.
All thread libraries I know (e.g. recent glibc or musl-libc) are using the low-level clone(2) system call for their thread implementations (and some C libraries are even using clone to fork a process).
clone is a difficult Linux syscall. Unless you are a thread library implementor, you should not use it directly but only thru library functions (like e.g. pthread_create(3)); see also futex(7) used in pthread_mutex* functions
The clone syscall is used to create tasks: either threads (sharing address space in a multi-threaded process) or processes.
The exit_group syscall is related to exiting these tasks.
In short, you'll never use directly exit_group or clone. Your libc is doing that for you. So don't care about exit_group or _Exit; you should use the standard library function exit(3) only, which deals notably with atexit(3) & on_exit(3) registered handlers and flushes <stdio.h> buffers. In the rare cases you don't want that to happen, use _exit(2) (but you probably don't need that).
Of course, if you are reimplementing your own libc from scratch, you need to care about exit_group & clone; but otherwise you don't care about them..
If you care about gory implementation details, dive into the source code of your libc. Details may be libc-version, kernel-version, and compiler specific!
Currently I'm trying to understand what happens when a shared library spawns a thread, which does not terminate and the shared library is then unloaded.
What happens to the thread if the parent does not wait for the thread to exit?
Does the thread die or does it remain in the running state?
If it does then how can the parent detect when it's being unloaded and somehow terminate the thread?
Thanks for any help.
I assume the shared library is some plugin dynamically loaded at runtime using dlopen(3) and later explicitly unloaded using dlclose.
The dlopen and dlclose functions are internally using a reference counter and they are mmap(2)-ing (for dlopen) and munmap-ing (for dlclose) some segments inside the ELF shared object when appropriate (i.e. when the ref counter crosses the 0 border).
If a thread is running some function inside the dlclose-d shared library, the code of that function becomes munmap-ed and as soon as you jump (or return into) that function, you get a SIGBUS, SIGILL or SIGSEGV signal.
So you don't want that munmapto happen: hence you could:
avoid calling dlclose; this works very well in practice (unless you have a server program), because mmap consumes mostly address space for text read-only segments of shared object. As my manydl.c demonstrates, you can dlopen hundreds of thousands of shared objects on a desktop without reaching serious limits.
or pass RTLD_NODELETE to dlopen asking it to never unmap the library
Alternatively, use some facilities (i.e. destructor-attributed functions in the shared library) or conventions (perhaps atexit(3)?) to be sure that the thread has ended before dlclose
Shared library is loaded into process, so spawn thread will run in process address space.
Thread will keep running if not noticed to exit. and when process is exit, thread will also be terminated.
As shared library spawn the thread, so it is better that shared library also provide a function which will notice thread to exit so process can call the function to exit thread before unload library.