I am learning threads and trying to implement a code which creates a thread. The thread writes into a file. If the thread has been created it returns 0 . The code here returns 0 but it does go into the function write() but does not writes in the file . Just to check it goes in the function i have put a printf() statement.I want the input should be taken by command line here but it also does not work so to make it simpler i have written only "hello world" to the file .
Here is the code :-
#include<stdio.h>
#include<stdlib.h>
#include<pthread.h>
void *write(void *arg)
{
printf("HI \n");
FILE *fp;
fp = fopen("file.txt", "a");
if (fp == NULL) {
printf("error\n");
} else {
fprintf(fp, "hello world");
}
}
int main()
{
pthread_t thread;
int tid;
tid = pthread_create(&thread, NULL, write, NULL);
printf("thread1 return %d \n", tid);
exit(0);
}
I suspect what's happening is the exit() call is executing before the fprintf() gets to the point of putting content into the buffer.
pthread_create() returns after creating the thread, not after the thread finishes, and then both threads run simultaneously. Maybe this is your first "race condition"?
void *result; pthread_join(tid, &result); will wait for the function running in the other thread to return (and get it's return value).
correction
Forgot that the file pointer is not automatically closed, so this will thwart you as well. Call fflush() or fclose() after the fprintf.
You need to join with the thread to wait for it to finish before exiting your main program.
tid=pthread_create(&thread,NULL,write,NULL);
printf("thread1 return %d \n",tid);
pthread_join(thread, NULL);
exit(0);
Your thread function should return a value since it is declared to do so. Returning NULL is fine.
I think you shoudl this code:
#include <thread>
#include <fstream>
using namespace std;
void write(string filename)
{
ofstream outfile(filename);
outfile<<"Hello World!"<<endl;
outfile.close();
}
int main()
{
thread t(write, "file.txt");
t.join();
}
use this command to compile the code:g++ -g -std=c++11 test.cpp -lpthread
Related
Trying to see how pthread works by running a simple program but I am getting segmentation fault (core dumped) at pthread_create
#include <stdio.h>
#include <pthread.h>
#include <stdlib.h>
void* testfunc(void* arg) {
while (1) {
printf("testfunc");
}
}
int main(void) {
printf("helo\n");
if (pthread_create(NULL, NULL, &testfunc, NULL) != 0) {
perror("pthread failed to create\n");
}
while (1) {
printf("main function\n");
sleep(1000);
}
return 0;
}
What seems to be causing the problem? I am on Ubuntu 20.04 if that matters.
You can't pass NULL for pthread_create's first argument.
Before returning, a successful call to pthread_create() stores the ID of the new thread in the buffer pointed to by thread
Also, pthread_create doesn't set errno, so using perror makes no sense, at least not without some prep.
on error, it returns an error number, and the contents of *thread are undefined.
Fixed:
pthread_t thread;
if ( ( errno = pthread_create(&thread, NULL, &testfunc, NULL) ) != 0 ) {
perror("pthread failed to create\n");
}
...
pthread_join(thread, ...); // Normally.
Threads in c are very unforgiving. There are a few problems with your code that I can see.
First you might want to refer to the developer docs for p_thread. They are very well documented. What you currently have is a thread call but you are not pointing anything to that thread. This is why you are receiving the segmentation error. Meaning your program lost the pointer to that thread somewhere when it tried calling it. I suggest something like.
pthread_t thread;
int * argument = 5;
if(pthread_create(&thread,NULL, &testfunc, &argument) !=0){
// ^This is a pointer to your argument
// that you want to pass in
perror("pthread failed to create\n");
exit(1);
}
and your thread function will also need to be typecast from a void pointer into whatever you want it to return to work with. Then it needs to be cast back to a void pointer before is returned from the thread routine.
void* testfunc(void* arg){
int* testVar = (int *)arg;
// do some logic here
return (void *) testVar;
}
lastly you are responsible for your memory in C so you must kill the thread you created before exiting.
pthread_join(thread, NULL);
My number one suggestion is you watch some videos relating to it.
I use that very simple C program to execute a system call to php each second, in order to run a php script that sends pending push notification in my database to APNS (Apple notification service).
Anyway, this program causes a memory overflow after about 10 hours, so I reduced sleep time between thread creation from 1s to 10000us, and I could see in real time with htop that memory were increasing without never lower. Here is the program :
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
typedef struct {
char* script_path ;
} arg_for_script ;
static void *start_instance(void *_args)
{
int id = abs(pthread_self());
arg_for_script* args = _args ;
printf("[SERVICE] start php script on thread %d\n",id);
fflush(stdout);
char cmd[200] ;
sprintf(cmd, "php -f %s %d", args->script_path, id );
system(cmd);
printf("[SERVICE] end of script on thread %d\n", id);
fflush(stdout);
pthread_exit(NULL);
}
int main(int argc, char* argv[])
{
if(argc < 2)
{
fprintf(stderr, "[SERVICE] Path of php notification script must be filled\n");
fflush(stderr);
return EXIT_FAILURE;
}
arg_for_script args ;
args.script_path = argv[1];
pthread_attr_t tattr ;
struct sched_param param;
param.sched_priority = 1 ;
pthread_attr_init(&tattr);
pthread_attr_setinheritsched(&tattr, PTHREAD_EXPLICIT_SCHED);
pthread_attr_setschedpolicy(&tattr, SCHED_FIFO);
pthread_attr_setschedparam(&tattr, ¶m);
while(1) {
pthread_t thrd;
// if(pthread_create(&thrd, &tattr, start_instance, (void *)&args) == -1) {
if(pthread_create(&thrd, NULL, start_instance, (void *)&args) == -1)
{
fprintf(stderr, "[SERVICE] Unable to create thread\n");
fflush(stderr);
return EXIT_FAILURE;
}
usleep( 10000);
}
// pthread_attr_destroy(&tattr);
return EXIT_SUCCESS ;
}
Here, I don't dynamically allocate any RAM with malloc. Why would this program increases memory usage ? What pointer should I free here ?
You aren't calling pthread_join() nor use pthread_detach(), so the resources allocated for the thread aren't freed. Namely each thread has it's own stack, which is probably what causes the rising memory consumption.
Some remarks about your implementation: Since you plan on executing a PHP script with system() and don't actually need to work on shared variables or file descriptors, it's better to use fork() and one of the variants of exec(). This will spawn a new process without the intermediate step of creating a thread. It's also not recommended to use system() because it often allows to exploit the program when the input isn't properly sanitized. In this case it might be fine, if you only call it manually.
First, I've been reading some comments in forums about it's recommended to avoid using fork in threads, and popen does fork.
Anyway, I'm doing a program with some threads and it'll be very useful for me to using other library functions which execute popen.
When I do that, program exits.
Let me put a simple example because the code is large:
int main()
{
pthread_t thread1, thread2;
int var=1;
pthread_create(&thread1, NULL, mythread, &var);
pthread_create(&thread2, NULL, anotherthread, &var);
...
}
void *mythread(void *s)
{
...
pthread_detach(pthread_self());
...
printf("this is printed\n");
char *str = externalFunctWithPopen();
printf("this is NEVER printed\n");
...
}
char *externalFunctWithPopen()
{
...
printf("this is also printed\n");
popf = popen(command, "r");
printf("this is not printed at all\n");
while (fgets(buf, sizeof(buf), popf) != 0) {
...
}
As I told before, "this is NEVER printed" is never printed, and furthermore, main exits, including the other thread called anotherthread
Any piece of help is welcome.
main exits, including the other thread
To avoid the behaviour that leaving main() tears down all other threads of the same process. leave it via a call to pthread_exit() instead of doing exit() or just return.
I'm fairly new to threads in C. For this program I need to declare a thread which I pass in a for loop thats meant to print out the printfs from the thread.
I can't seem to get it to print in correct order. Here's my code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 16
void *thread(void *thread_id) {
int id = *((int *) thread_id);
printf("Hello from thread %d\n", id);
return NULL;
}
int main() {
pthread_t threads[NUM_THREADS];
for (int i = 0; i < NUM_THREADS; i++) {
int code = pthread_create(&threads[i], NULL, thread, &i);
if (code != 0) {
fprintf(stderr, "pthread_create failed!\n");
return EXIT_FAILURE;
}
}
return EXIT_SUCCESS;
}
//gcc -o main main.c -lpthread
That's the classic example of understanding multi-threading.
The threads are running concurrently, scheduled by OS scheduler.
There is no such thing as "correct order" when we are talking about running in parallel.
Also, there is such thing as buffers flushing for stdout output. Means, when you "printf" something, it is not promised it will happen immediately, but after reaching some buffer limit/timeout.
Also, if you want to do the work in the "correct order", means wait until the first thread finishes it's work before staring next one, consider using "join":
http://man7.org/linux/man-pages/man3/pthread_join.3.html
UPD:
passing pointer to thread_id is also incorrect in this case, as a thread may print id that doesn't belong to him (thanks Kevin)
#include <stdio.h>
#include <process.h>
void sayit(void * arg) {
printf("hello, world! from child process\n");
_endthread();
}
int main(int argc, char ** argv) {
if (_beginthread(sayit, 16, NULL) == -1)
printf("Error\n");
return 0;
}
By idea program must print string in function sayit but it doesn't happen.
Is there any functions to determine had process completed or it still working?
Can you give me links to full documentation for process.h?
You spawn a thread but you don't wait for it. So high chance that the program ends before the second thread is resumed. Use _beginthreadex and WaitForSingleObject or Boost.Threads which have a 'join' function.
When you start a thread in a non-suspended state there is no guarantee when the thread will start so it may just be that the program ends before the thread has started or just as the thread is starting.
In order to make sure the thread runs you need to do something like
unsigned threadID = 0;
HANDLE hd = (HANDLE)_beginthreadex( NULL, 0, sayit, NULL, 0, &threadID);
WaitForSingleObject( hd, INFINITE ); // this will wait for thread to end
CloseHandle(hd);