0

I have the following code and I make ps aux | grep myprogram in each step of the main() code of myprogram (name of the application I build).

At the beggining of the execution of myprogram, the ps aux | grep myprogram show only 1 time the myprogram in the list

after cancelling a thread that I created in the begging of the main(), the ps aux | grep myprogram show the myprogram twice and I expected to get only 1.

Could some one explain this behaviour? and how to return to the initial situation (only 1 myprogram)

#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>

pthread_t test_thread;

void *thread_test_run (void *v)
{
    int i=1;
    while(1)
    {
       printf("into thread %d\r\n",i);
       i++; 
       sleep(1);
    }
    return NULL
}

int main()
{
    // ps aux | grep myprogram  ---> show only 1 myprogram

    pthread_create(&test_thread, NULL, &thread_test_run, NULL);

    // ps aux | grep myprogram  ---> show  3 myprogram

    sleep (20);  


    pthread_cancel(test_thread);

    // ps aux | grep myprogram  ---> show 2 myprogram and I expected only 1 !!??

   // other function are called here...

    return 0;
}

EDIT

the libc used by the linux is libc-0.9.30.1.so

# ls -l /lib/| grep libc
-rwxr-xr-x    1 root     root        16390 Jul 11 14:04 ld-uClibc-0.9.30.1.so
lrwxrwxrwx    1 root     root           21 Jul 30 10:16 ld-uClibc.so.0 -> ld-uClibc-0.9.30.1.so
lrwxrwxrwx    1 root     root           21 Jul 30 10:16 libc.so.0 -> libuClibc-0.9.30.1.so
-rw-r--r--    1 root     root         8218 Jul 11 14:04 libcrypt-0.9.30.1.so
lrwxrwxrwx    1 root     root           20 Jul 30 10:16 libcrypt.so.0 -> libcrypt-0.9.30.1.so
-rw-r--r--    1 root     root       291983 Jul 11 14:04 libuClibc-0.9.30.1.so
MOHAMED
  • 41,599
  • 58
  • 163
  • 268

3 Answers3

3

I'll assume you have some outdated glibc (version 2.2 or 2.3), which used the "linuxthreads" implementation of pthread.

In this older library one additional thread is created by the library for thread management; it can be created after first call to pthread_create; but it will sleep most time.

In newer linuxes there is glibc with NPTL ("Native posix thread library") implementation. When it is used, you will not see threads in ps axu; use ps axum (with m) to see native threads. And NPTL not uses a management thread.

PS Check http://pauillac.inria.fr/~xleroy/linuxthreads/faq.html D.5 answer:

D.5: When I'm running a program that creates N threads, top or ps display N+2 processes that are running my program. What do all these processes correspond to?

Due to the general "one process per thread" model, there's one process for the initial thread and N processes for the threads it created using pthread_create. That leaves one process unaccounted for. That extra process corresponds to the "thread manager" thread, a thread created internally by LinuxThreads to handle thread creation and thread termination. This extra thread is asleep most of the time.

PPS: Thanks, Mohamed KALLEL; thanks, mux: libc-0.9.30.1 is uClibc and seems that it uses same outdated linuxthreads implementation (which is known to be not fully posix-compatible). Here is changelog: http://web.archive.org/web/20070609171609/http://www.uclibc.org/downloads/Changelog

0.9.10 21 March 2002

Major new features: o pthreads support (derived from glibc 2.1.3's linuxthreads library) by Stefan Soucek and Erik Andersen

osgx
  • 90,338
  • 53
  • 357
  • 513
  • 1
    Besides, calling `pthread_cancel` doesn't guarantee that thread will be killed immediately. – P.P Nov 08 '12 at 14:21
  • @KingsIndian actually `sleep` is a cancellation point `man 7 pthreads` so the thread should be cancelled at that point if the main code waits for a while. – iabdalkader Nov 08 '12 at 14:28
  • @mux Is it guaranteed that a thread will be cancelled immediately upon reaching a cancellation point? – P.P Nov 08 '12 at 14:39
  • @KingsIndian the man page doesn't say it's `not` guaranteed, it says cancellation will be delayed until the thread calls cancellation point. Not sure if that means it's guaranteed. – iabdalkader Nov 08 '12 at 14:41
0

Could be an older pthreads implementation as suggested by the other answers, however, if you are using a glibc 2.4 or higher which uses NPTL, then note that the ps command you used won't even show threads, instead use:

ps -AL

The output before and after pthread_cancel() is:

$ ps -AL | grep tst
  983   983 pts/2    00:00:00 tst
  983   984 pts/2    00:00:00 tst
$ ps -AL | grep tst
  983   983 pts/2    00:00:00 tst

There's more information about it here specifically about uclibc since it doesn't have NPTL, then ps aux should show all the threads.

Since the introduction of the Native POSIX Threads Library (NPTL) threads have become rather elusive. They don't show up in the default process listing using the ps command if you do have the luxury of the full ps command (from the procps package) on your target system then all you need to do is add the “-L” option.

iabdalkader
  • 17,009
  • 4
  • 47
  • 74
  • mux, are you sure that your setup is the same as of KALLEL? – osgx Nov 08 '12 at 14:03
  • @osgx I've tested his code, that's irrelevant, `ps aux` doesn't even show threads in the output :) – iabdalkader Nov 08 '12 at 14:04
  • So, it is a mark that you and he have different glibc versions with different pthread implementations. Because he sees threads in `ps aux`. – osgx Nov 08 '12 at 14:06
  • @osgx I've updated the answer, to take that into account, is it more clear now ? – iabdalkader Nov 08 '12 at 14:08
  • 1
    linuxthreads uses no threads; it will emulate threads using processes with all shared memory. This is a cause to see "threads" (really processes) in `ps aux`. – osgx Nov 08 '12 at 14:09
  • @osgx and if he's using a newer implementation ? there will be no management thread, right ? – iabdalkader Nov 08 '12 at 14:21
  • if he uses newer pthreads (the NTPL), then he will see only single line in output of `ps axu`. But yes, in `ps axum` there will be no extra threads for management. – osgx Nov 08 '12 at 14:27
  • @osgx then I guess we'll have to wait and see, by the way, NPTL doesn't use threads either, a thread is a process sharing memory with its parent. – iabdalkader Nov 08 '12 at 14:31
  • NPTL really uses threads; because the 'm' option of ps is needed to see them. They are created with `clone` syscall with `CLONE_THREAD` flag (http://linux.die.net/man/2/clone): "If CLONE_THREAD is set, the child is placed in the same thread group as the calling process." – osgx Nov 08 '12 at 15:21
  • @osgx I'm sorry, but that doesn't make sense to me, if that's true, then there will be two different constructs in the kernel to represent threads and processes (just like in Windows), and that's not true, processes and threads are represented by the `task_t sturct` in the Linux kernel and the kernel makes no distinction between them. and the man page also says `the term "thread" is used to refer to the processes within a thread group` – iabdalkader Nov 09 '12 at 10:23
  • Linux and NPTL uses 1:1 model for mapping threads to kernel' tasks (one task_struct for one thread). So any schedulerable thing is task_struct. But the "process" (in general) is closer to term "thread group". And in the "processes within a thread group" process was used as "something that has own task_struct". – osgx Nov 09 '12 at 12:25
0

You have an (very) old linux system, where your threads are shown as processes by tools such as ps, which will not happen on newer linux systems

However, a thread is normally not entierly disposed of when it returns or you kill/cancel it.

For that to happen you have to call pthread_detach(pthread_self()) in your thread or create the thread in detached state: A detached thread will dispose it's thread resources when that thread ends, and a detached thread cannot be joined by pthread_join() later.

pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, 1);
pthread_create(&test_thread, &attr, &thread_test_run, NULL);

Or you have to call pthread_join() on it, e.g.

pthread_create(&test_thread, NULL, &thread_test_run, NULL);

sleep (20);  
pthread_cancel(test_thread);
pthread_join(test_thread);

pthread_join() will ensure the thread resources are released.

The concept is roughly analogous to zombie processes, where a process is not entierly disposed of until a parent calls wait() or similar on that process.

nos
  • 223,662
  • 58
  • 417
  • 506