Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flow of program execution during Thread creation

I am new to threads.

I have written a sample program to create a thread.

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


void * func(void * temp)
{
    printf("inside function\n");
    return NULL;
}

int main()
{
    pthread_t pt1;
    printf("creating thread\n");
    pthread_create(&pt1,NULL,&func,NULL);
    printf("inside main created thread\n");

return 0;
}

After compilation the answer is found to be :

creating thread
inside main created thread
inside function
inside function

I understand that answer may vary as return 0; may be called before the printf in func is executed. But how come in the solution, inside function is printed two times?

On compiling With gcc -o temp thread1.c -lpthread on first run:

creating thread
inside main created thread

on second run:

creating thread
inside main created thread
inside function
inside function

On compiling with gcc -pthread -o temp thread1.c On first run:

creating thread
inside main created thread
inside function
inside function

I have observed this behavior on

gcc version: 4.4.3 (Ubuntu 4.4.3-4ubuntu5)
Kernel release:2.6.32-24-generic
glib version:2.11.1
like image 387
starkk92 Avatar asked Aug 04 '14 11:08

starkk92


People also ask

What is the process of threading?

In manufacturing, threading is the process of creating a screw thread. More screw threads are produced each year than any other machine element.

How do threads execute?

On a multiprocessor or multi-core system, multiple threads can execute in parallel, with every processor or core executing a separate thread simultaneously; on a processor or core with hardware threads, separate software threads can also be executed concurrently by separate hardware threads.

What is thread process and program?

A process refers to the code and data in memory segments into which the operating system loads a program. Simply put, a process is a program that is loaded into the memory to be executed by the processor. A thread is the minimum execution unit of code managed by the operating system.

Which is used to control flow the order of processing of sample in a thread?

The order in which the threads should be run will be controlled by the order in which you insert them into the ArrayList. You call the runThreads method with a String and the threads will run in that sequence.


2 Answers

I observed this issue on gcc version 4.6.3 (Ubuntu/Linaro 4.6.3-1ubuntu5), glib version 2.15 with O2 flag. Without any optimization flag, this issue is not observed.

Why the output is strange
The C language specification does not make reference to any particular compiler, operating system, or CPU. It makes reference to an abstract machine that is a generalization of actual systems. This abstract machine (atleast up to C99 specs) is single threaded. So standard libraries (including printf) are not required to be thread safe by default. If you are using standard library functions across the threads (using some library for example posix libpthread), you are responsible for adding synchronization (mutex, semaphore, condvar etc) before accessing non-entrant standard library functions. If you don't, there may be surprising results from time to time and you should use at your own risk.

Some analysis at the environment where I can reproduce this issue
Analyzing the assembly generated for both version of flag, I can not find any significant difference (Onething noticeable, printfs are converted to puts)

Looking at the source for puts

int
_IO_puts (str)
     const char *str;
{
  int result = EOF;
  _IO_size_t len = strlen (str);
  _IO_acquire_lock (_IO_stdout);

  if ((_IO_vtable_offset (_IO_stdout) != 0
       || _IO_fwide (_IO_stdout, -1) == -1)
      && _IO_sputn (_IO_stdout, str, len) == len
      && _IO_putc_unlocked ('\n', _IO_stdout) != EOF)
    result = MIN (INT_MAX, len + 1);

  _IO_release_lock (_IO_stdout);
  return result;
}

#ifdef weak_alias
weak_alias (_IO_puts, puts)
#endif

It seems the problem lies in _IO_putc_unlocked('\n', _IO_stdout). This may flush the stream and may get killed before updating the stream state.

Learnings for multithreaded coding
When the main thread returns, it terminates the entire process. This includes all other threads. So signal all children threads to exit (or use pthread_kill) and either make main thread exit with pthread_exit or use pthread_join.

like image 99
Mohit Jain Avatar answered Nov 15 '22 07:11

Mohit Jain


In general you can't assume that printf and related memory structures are thread-safe. It depends on the way stdio library has been implemented. In particular, malfunctions may happen when threads and processes are terminating, since the runtime library usually flushes the output buffers before exiting. I have already seen such a sort of behavior, and the solution is usually a mutex or semaphore to protect the output operations (more precisely, to protect the accesses to FILE objects).

like image 38
Giuseppe Guerrini Avatar answered Nov 15 '22 05:11

Giuseppe Guerrini