Q 1 How to create Thread , Get status and Synchronize ?
Ans Get Status :
1) thread must call pthread_join(threads[t] ,&status); where void *status = NULL;
this status can be retrieved by caller
printf("Main: completed join with thread having a status of %lu\n",(long)status);
Don t fetch *status it will core dump
Thread creator must call either
pthread_join or pthread_detach() [this is applicable if thread is not created as Attribute detachable by default threads are non detachable ]
pthread_detach() function indicates that system resources for the specified thread should be reclaimed when the thread ends. pthread_detach() routine can be used to explicitly detach
a thread even though it was created as joinable.
After pthread_detach() has been issued, it is not valid to try to pthread_join() with the target thread.
----- The pthread_join() function waits for a thread to terminate, detaches the thread, then returns the threads exit status. if it was specified in the target thread's
call to pthread_exit().
If thread resources are not freed even if threads are complete resources will not get freed and after 200-250 threads creation errorno 11 will be return "Resource temporarily unavailable".
2) Thread can give status back by return or pthread_exit(); both are same
Note : When a joinable thread terminates, its memory resources (thread
descriptor and stack) are not deallocated until another thread performs
pthread_join on it. Therefore, pthread_join must be called once for
each joinable thread created to avoid memory leaks.
man of pthread_exit()
The pthread_exit() function terminates the calling thread and returns a value via retval that (if
the thread is joinable) is available to another thread in the same process that calls
pthread_join(3).
Any clean-up handlers established by pthread_cleanup_push(3) that have not yet been popped, are
popped (in the reverse of the order in which they were pushed) and executed. If the thread has any
thread-specific data, then, after the clean-up handlers have been executed, the corresponding
destructor functions are called, in an unspecified order.
When a thread terminates, process-shared resources (e.g., mutexes, condition variables, semaphores,
and file descriptors) are not released, and functions registered using atexit(3) are not called.
After the last thread in a process terminates, the process terminates as by calling exit(3) with an
exit status of zero; thus, process-shared resources are released and functions registered using
atexit(3) are called.
Q2 If main creats two thread and exits will thread stay? or if main creats T1 and T1 creats T2 and T1 dies What will be the fate to T2 then ?
Ans: Exiting of main() forces all child threads to kill as process cleans up .
But it can be avoided by putting
pthread_exit(NULL); in main this will enable threads to sustain even after main .
One more way is to JOIN all the treads created : it also blocks Father to wait child thread die . Main use of join call is to get status of thread after Execution
void * status;
pthread_join(threads[t] ,&status); this has to be call for each thread created .
Q3 Do pthread have PId ? Realation b/w TID and PID ?
Ans : Yes its
LWP-id they have can be viewed by
ps -eLF // -L option is to Show threads, possibly with LWP and NLWP columns
ps -emf // -m is for Show threads after processes
user$ ps -eLf | grep 5708 //5708 is pid of main thread which spawns two thread.
UID PID PPID
LWP C NLWP STIME TTY TIME CMD
user 5708 11297
5708 0 3 13:28 pts/2 00:00:00 ./a.out
user 5708 11297
5709 0 3 13:28 pts/2 00:00:00 ./a.out
user 5708 11297
5710 0 3 13:28 pts/2 00:00:00 ./a.out
user 5726 10354 5726 0 1 13:29 pts/1 00:00:00 grep --color=auto 5708
ALL threads share PID ( getpid())of parent. But LWP id will be different.
In a single-threaded process, the thread ID is equal to the process ID (PID, as returned by getpid(2)). In a multithreaded process, all threads have the same PID, but each one has a unique TID
To get tid use : pid_t gettid(void);
pid_t tid;
tid = syscall(SYS_gettid);
POSIX thread id (its different from TID )
pthread_t pthread_self();
long tid = pthread_self();
note:for printing use %lu as its big on in %ld it might be NEGATIVE
From MAN page :
In the Linux kernel, a kernel-scheduled thread is not a distinct construct from a process.
Instead, a thread is simply a process that is created using the Linux-unique clone(2) system call;
other routines such as the portable pthread_create(3) call are implemented using clone(2). Before Linux 2.4, a thread was just a special case of a process, and as a consequence one thread could not wait on the children of another thread, even when the latter belongs to the same thread group. However, POSIX prescribes such functionality, and since Linux 2.4 a thread can, and by default will, wait on children of other threads in the same thread group.
The following Linux-specific options are for use with children created using clone(2); they cannot
be used with waitid():
__WCLONE
Wait for "clone" children only. If omitted then wait for "non-clone" children only. (A
"clone" child is one which delivers no signal, or a signal other than SIGCHLD to its parent
upon termination.) This option is ignored if __WALL is also specified.
__WALL (since Linux 2.4)
Wait for all children, regardless of type ("clone" or "non-clone").
__WNOTHREAD (since Linux 2.4)
Do not wait for children of other threads in the same thread group. This was the default
before Linux 2.4.
Q4 What Zombie Process , Orphan Process, Defunct Process (in ps -eaf )
Ans : Zombie and defunct are same it is is a process that has completed execution but still has an entry in the process table. Reason of the entry is parent didn't call wait() or waitpid() for child these are the calls Required to get status of child process and removes entry form Process table .
Absence of these causes a child process to become Zombie
An
orphan process is a process that is still executing, but whose parent has died. They do not become zombie processes; instead, they are adopted by init (process ID 1), which waits on its children.
Q5 Debugging with GDB with Threads ?
Ans : compile with -g flag . that will be helpful
get pid by: ps -eaf | grep exename
run gdb -p pid
Reading symbols from /lib/tls/libpthread.so.0...(no debugging symbols found)...done.
[Thread debugging using libthread_db enabled]
[New Thread -1218548928 (LWP 11719)]
[New Thread -1218552912 (LWP 11721)]
(gdb) info threads
2 Thread -1218552912 (LWP 11721) 0x08048559 in PrintHello ()
1 Thread -1218548928 (LWP 11719) 0x00d0ad58 in pthread_join () from /lib/tls/libpthread.so.0
(gdb) t 2
[Switching to thread 2 (Thread -1218540624 (LWP 18808))]#0 0x08048552 in PrintHello (threadid=0x0)
at thread.c:18
18 for(u=0;u<10000;u++)
(gdb) bt
#0 0x08048552 in PrintHello (threadid=0x0) at thread.c:18
#1 0x00407dd8 in start_thread () from /lib/tls/libpthread.so.0
#2 0x001edd1a in clone () from /lib/tls/libc.so.6
putting BreakPoint
(gdb)break linespec thread threadno
Q5 tracking threads with PS -eLF and strace.
gdb uses ptrace only
-----------------------------------------------
compiling "gcc thread.c -pthread"
-------------
Code :
---------------Output ---
case 1 :code as above
In main: creating thread 0
Hello World! It's me, thread #0!
done thread #0!
In main: creating thread 1
Hello World! It's me, thread #1!
done thread #1!
--------main is leaving
------------------------------
case 2 commenting these two
in main function
In main: creating thread 0
Hello World! It's me, thread #0!
In main: creating thread 1
Hello World! It's me, thread #1!
--------main is leaving
main left
----------------------------
------O/P--------------------
case 3 : putting just this in main
------------------------------------
In main: creating thread 0
Hello World! It's me, thread #0!
In main: creating thread 1
Hello World! It's me, thread #1!
--------main is leaving
done thread #0!
done thread #1!
Note : thread were workiing even after main thats Magic of pthread_exit(NULL) in main
Links to refer
https://computing.llnl.gov/tutorials/pthreads/#Compiling
http://www.yolinux.com/TUTORIALS/LinuxTutorialPosixThreads.html