The Idea here is to create a file to be written to. I'm trying to create ten threads and have them print to the file 10 times each. Using a semaphore to stop multiple threads from writing to the file at once. But I have errors. The code is below:
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define FNAME "fisier.txt"
#define MAX_STRING_LEN 80
#define NUMBER_OF_THREADS 10
FILE *fp;
sem_t mutex;
int counter;
FILE *makeTextFile(char *fname, char mode){
FILE *localFP;
localFP = fopen(fname, &mode);
return (localFP);
}
void *print_message(void *tid){
int i;
for (i = 0; i < 10; i++){
sem_wait(&mutex);
fp = fopen(FNAME, "a");
fprintf(fp, "Thread %d is running.\n", tid);
fclose(fp);
sem_post(&mutex);
printf ( "Thread %d has finished.\n", tid);
}
}
int threads(){
const char *fName = "fisier.txt";
int status;
pthread_t threads[NUMBER_OF_THREADS];
fp = makeTextFile(FNAME, 'w');
fprintf(fp, "Process ID: %ld\n", (long)getpid());
fclose(fp);
int i;
for (i =0; i < NUMBER_OF_THREADS; i++){
status = pthread_create(&threads[i], NULL, &print_message, (void *)i);
if (status != 0){
printf("pthread_create returned error code %d\n", status);
exit(-1);
}
}
}
int main() {
threads();
return 0;
}
Warnings:
probl2.c: In function ‘print_message’:
probl2.c:27:21: warning: format ‘%d’ expects argument of type ‘int’, but argument 3 has type ‘void *’ [-Wformat=]
fprintf(fp, "Thread %d is running.\n", tid);
^
probl2.c:30:14: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘void *’ [-Wformat=]
printf ( "Thread %d has finished.\n", tid);
^
probl2.c: In function ‘threads’:
probl2.c:44:68: warning: cast to pointer from integer of different size [-Wint-to-pointer-cast]
status = pthread_create(&threads[i], NULL, &print_message, (void *)i);
Writing in a file just it: Process ID: 10568
I want to write
How to solve it ?
A couple of things I noticed:
You are not initializing your semaphore. Use sem_init to do this (and use sem_destroy when you are finished).
You are not joining on your threads. The program will exit without waiting for the threads to finish. You can use pthread_join in a loop to make sure all threads have finished.
Here is an updated version of your threads function. In production code I would check the return values of the functions I added.
void threads(){
const char *fName = "fisier.txt";
int status;
pthread_t threads[NUMBER_OF_THREADS];
fp = makeTextFile(FNAME, 'w');
fprintf(fp, "Process ID: %ld\n", (long)getpid());
fclose(fp);
sem_init(&mutex,0,1);
int i;
for (i =0; i < NUMBER_OF_THREADS; i++){
status = pthread_create(&threads[i], NULL, &print_message, (void*)i);
if (status != 0){
printf("pthread_create returned error code %d\n", status);
exit(-1);
}
}
void* value = NULL;
for (i = 0; i < NUMBER_OF_THREADS; i++) {
pthread_join(threads[i], &value);
}
sem_destroy(&mutex);
}
Related
This code is about.
Race conditions:
Scheduling and compiler behaviour play a significant role in process or thread synchronization. The simplest scenario to demonstrate the need to synchronization comes from the race conditions created between two threads/process trying to modify a value of a shared variable, which typically results in data inconsistency, and erroneous results. The following example demonstrates this situation:
I'm new to C and am having trouble with what is happening with this warning. What does the warning mean and how can i fix it. The code i wrote is here:
q1.c: In function ‘runner’:
q1.c:13:1: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long int’ [-Wformat=]
printf("T tid: %d x before: %d\n", syscall(SYS_gettid),x); int i;
^
q1.c:19:1: warning: format ‘%d’ expects argument of type ‘int’, but argument 2 has type ‘long int’ [-Wformat=]
printf("T tid: %d x after: %d\n", syscall(SYS_gettid),x);
Here's the code:
// Race condition
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/syscall.h>
int x=0;
void * runner(void *arg)
{
printf("T tid: %d x before: %d\n", syscall(SYS_gettid),x); int i;
for (i = 0; i < 100000; i++ )
{
x = x + 1;
}
printf("T tid: %d x after: %d\n", syscall(SYS_gettid),x);
}
int program()
{
pthread_t t1,t2,t3,t4;
printf("Parent pid: %d x before threads: %d\n", getpid(),x); int i;
if(pthread_create(&t1,NULL, runner, NULL)){ printf("Error creating thread 1\n"); return 1;
}
if(pthread_create(&t2,NULL, runner, NULL)){ printf("Error creating thread 2\n"); return 1;
}
if(pthread_create(&t3,NULL, runner, NULL)){ printf("Error creating thread 1\n"); return 1;
}
if(pthread_create(&t4,NULL, runner, NULL)){ printf("Error creating thread 1\n"); return 1;
}
if(pthread_join(t1,NULL)){ printf("error joining thread 1"); return 1;
}
if(pthread_join(t2,NULL)){ printf("error joining thread 1"); return 1;
}
if(pthread_join(t3,NULL)){ printf("error joining thread 1"); return 1;
}
if(pthread_join(t4,NULL)){ printf("error joining thread 1"); return 1;
}
printf("Parent pid: %d x after threads: %d\n", getpid(),x); return 0;
}
int main(int argc, char *argv[]) {
int count=0;
// loop runs the program count times
while(count<5)
{
// running program program();
count++;
//reset global x for next run of program. x=0;
printf("\n\n");
}
return 0;
}
You have to change "%d" with "%ld", "%d" is for signed int and here the l stands for long so "%ld" is for signed long int.
The prototype for syscall() returns a long
#include <sys/syscall.h>
long syscall(long number, ...);
When calling printf(), its format specifiers, like "%d", should match the type of the parameter (after the parameter goes through the usual promotions for a variadic argument). Change to
v---- long --------v
v----------- int ----------v
printf("T tid: %ld x before: %d\n", syscall(SYS_gettid), x);
Code should always be written with the idea of a human is going to read it.
even the writer had significant problems reading the code
as shown by the many 'copy-and-paste' errors
Note: when a '//' comment is started on a line, ALL the rest of the line is a comment
any functions, other than main, should have a prototype.
The method of stating the called functions before any function that calls them
will work for trivial programs, but not for multi file programs nor
programs with crossing call paths
I.E. always supply prototype statements.
When calling some function, always know (I.E. look it up) the full details
about that function. In the case of the OPs posted code,
this especially applies to the syscall() function.
When writing threads, there is more to know than just the prototype
for a thread. As in the OPs code, also need to know how to exit the thread
ALWAYS ALWAYS enable all warnings when compiling. Warnings are problems
in the code that should be fixed before continuing.
BTW: the use of a single mutex would have eliminated the race condition problem
// Race condition
#include <pthread.h>
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/syscall.h>
void *runner( void * );
int program( void );
int x=0;
// <-- compiler raises warning about unused parameter
void * runner(void *arg)
{
// the returned value from the syscall is a long int
//printf("T tid: %d x before: %d\n",
printf("T tid: %ld x before: %d\n",
syscall(SYS_gettid),
x);
int i;
for (i = 0; i < 100000; i++ )
{
x = x + 1;
}
// <-- the returned value from syscall is a long int
//printf("T tid: %d x after: %d\n",
printf("T tid: %ld x after: %d\n",
syscall(SYS_gettid),
x);
// <-- this line missing, compiler raises warning
pthread_exit(NULL);
} // end function: runner
int program()
{
pthread_t t1,t2,t3,t4;
printf("Parent pid: %d x before threads: %d\n",
getpid(),
x);
//int i; // <-- this variable not used, results in compiler warning
if( pthread_create(&t1, NULL, runner, NULL) )
{
printf("Error creating thread 1\n");
return 1;
}
if( pthread_create(&t2, NULL, runner, NULL) )
{
printf("Error creating thread 2\n");
return 1;
}
if( pthread_create(&t3, NULL, runner, NULL) )
{
// <-- copy and paste error
//printf("Error creating thread 1\n");
printf("Error creating thread 3\n");
return 1;
}
if( pthread_create(&t4, NULL, runner, NULL) )
{
// <-- copy and paste error
//printf("Error creating thread 1\n");
printf("Error creating thread 4\n");
return 1;
}
if( pthread_join(t1, NULL) )
{
printf("error joining thread 1");
return 1;
}
if( pthread_join(t2, NULL) )
{
// <-- copy and paste error
//printf("error joining thread 1");
printf("error joining thread 2");
return 1;
}
if( pthread_join(t3, NULL) )
{
// <-- copy and paste error
//printf("error joining thread 1");
printf("error joining thread 3");
return 1;
}
if( pthread_join(t4, NULL) )
{
// <-- copy and paste error
//printf("error joining thread 1");
printf("error joining thread 4");
return 1;
}
printf("Parent pid: %d x after threads: %d\n",
getpid(),
x);
return 0;
} // end function: program
// <-- this line cause compiler to raise two warnings about unused parameters
//int main(int argc, char *argv[])
int main()
{
int count=0;
// <-- there is no loop code perhaps you meant to put the 'while' on the next line
// loop runs the program count times while(count<5)
while( count < 5 )
{
// <-- program is not run, perhaps you meant to put the 'program()' on the next line
// running program program();
program();
count++;
// <-- x is not being reset, perhaps you menat to put 'x=0;' on the next line
//reset global x for next run of program. x=0;
x=0;
printf("\n\n");
}
return 0;
} // end function: main
The Idea here is to create a file to be written to. I'm trying to create ten threads and have them print to the file 10 times each. Using a semaphore to stop multiple threads from writing to the file at once. Everything compiles and I don't get an error exit, however I can't understand why running the program numerous times: 1)It doesn't print 100 lines to the file, infact it's far less 2) The number of lines printed to the file vary each time.
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <pthread.h>
#include <semaphore.h>
#define READ "r"
#define NEW "w"
#define ADD "a"
#define NL "\n"
#define TAB "\t"
#define FNAME "PROCTAB.txt"
#define MAX_STRING_LEN 80
#define NUMBER_OF_THREADS 10
FILE *fp;
sem_t mutex;
int counter;
FILE *makeTextFile(char *fname, char mode){
FILE *localFP;
localFP = fopen(fname, &mode);
return (localFP);
}
void *print_message(void *tid){
int i;
for (i = 0; i < 10; i++){
sem_wait(&mutex);
fp = fopen(FNAME, ADD);
fprintf(fp, "Thread %d is running.\n", tid);
fclose(fp);
sem_post(&mutex);
}
}
int threads(){
const char *fName = "PROCTAB.txt";
int status;
pthread_t threads[NUMBER_OF_THREADS];
fp = makeTextFile(FNAME, 'w');
fprintf(fp, "Process ID: %ld\n", (long)getpid());
fclose(fp);
int i;
for (i =0; i < NUMBER_OF_THREADS; i++){
status = pthread_create(&threads[i], NULL, &print_message, (void *)i);
if (status != 0){
printf("pthread_create returned error code %d\n", status);
exit(-1);
}
}
return 0;
}
My main function is contained in a separate file.
You need to wait for all thread to finish before you exit the program.
if you add trace you will see which thread is finish.
void *print_message(void *tid){
int i;
for (i = 0; i < 10; i++){
sem_wait(&mutex);
fp = fopen(FNAME, ADD);
fprintf(fp, "Thread %d is running.\n", tid);
fclose(fp);
sem_post(&mutex);
printf ( "Thread %d has finished.\n", tid);
}
}
This is how you wait for all threads to finish
/* Wait for Threads to Finish */
for (i=0; i<NUMTHREADS; i++) {
pthread_join(thread[i], NULL);
}
I keep getting a seg fault (core dump) after pthread_join in my program. It prints out the expected result just fine, but seg faults when joining the thread. I have looked at several other discussions on this topic, but none of the suggested solutions seem to work in my case. Here is what my compile command looks like (no compile warnings or errors):
$ gcc -Wall -pthread test.c -o test
Here is the output:
$ ./test
1 2 3 4 5 6 7 8 9 10
Segmentation fault (core dumped)
And here is the code:
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int array[10];
void *fillArray(int *size) {
int i;
for (i = 0; i < *size; i++) {
array[i] = i+1;
}
return NULL;
}
int main (int argc, char *argv[])
{
int i, rc;
int size = 10;
pthread_t thread;
void *res, *end;
//initialize the array
for (i = 0; i < size; i++) {
array[i] = 0;
}
rc = pthread_create(&thread, NULL, fillArray(&size), &res);
if (rc != 0) {
perror("Cannot create thread");
exit(EXIT_FAILURE);
}
//print the array
for (i = 0; i < size; i++) {
if (array[i] != -1)
printf("%d ", array[i]);
}
printf("\n");
rc = pthread_join(thread, &end);
if (rc != 0) {
perror("Cannot join thread");
exit(EXIT_FAILURE);
}
return 0;
}
Any ideas what could be the cause?
This doesn't compile for me: It fails with
dummy.cpp: In function ‘int main(int, char**)’:
dummy.cpp:29: error: invalid conversion from ‘void*’ to ‘void* (*)(void*)’
dummy.cpp:29: error: initializing argument 3 of ‘int pthread_create(_opaque_pthread_t**, const pthread_attr_t*, void* (*)(void*), void*)’
Which is because you're actually calling fillArray and passing its result to pthread_create, rather than passing the function pointer. I expect your code will need to look more like this (UNTESTED!) : (Note I changed signature of fillArray, created data struct type to pass to fillArray, changed how pthread_create is called)
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int array[10];
struct fillArrayData {
int * array;
int size;
int * result;
};
void *fillArray(void *void_data) {
fillArrayData * data = (fillArray*)void_data;
for (int i = 0; i < data.size; i++) {
data.array[i] = i+1;
}
//You could fill in some return info into data.result here if you wanted.
return NULL;
}
int main (int argc, char *argv[])
{
int i, rc;
int size = 10;
pthread_t thread;
void *res, *end;
//initialize the array
for (i = 0; i < size; i++) {
array[i] = 0;
}
fillArrayData data;
data.array = array;
data.size = 10;
rc = pthread_create(&thread, NULL, fillArray, &data);
if (rc != 0) {
perror("Cannot create thread");
exit(EXIT_FAILURE);
}
//print the array
for (i = 0; i < size; i++) {
if (array[i] != -1)
printf("%d ", array[i]);
}
printf("\n");
rc = pthread_join(thread, &end);
if (rc != 0) {
perror("Cannot join thread");
exit(EXIT_FAILURE);
}
return 0;
}
Error in
Calling function pointer
passing parameter to thread handler
In pthread prototype of pthread_create below
int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
void *(*start_routine) (void *), void *arg);
1st argument - pthread_variable
2nd argument - thread attrubutes
3rd argument - thread handler(function pointer name)
4th argument - variable need to pass thread handler.
In 4th argument - if two thread want to share single variable, then create global variable, and the pass this variable when creating thread.
sample program:
#include <pthread.h>
#include <stdio.h>
#define NUM_THREADS 5
void *PrintHello(void *threadid)
{
long tid;
tid = (long)threadid;
printf("Hello World! It's me, thread #%ld!\n", tid);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t<NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, PrintHello, (void *)t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
pthread_exit(NULL);
}
further details here
Learning about pthreads, but I'm having trouble getting them created. Here is my output and the gdb information:
In main(), creating thread 1
ERROR: return code from pthread_create() is 22 for thread 1
In main(), creating thread 2
ERROR: return code from pthread_create() is 22 for thread 2
In main(), creating thread 3
ERROR: return code from pthread_create() is 22 for thread 3
In main(), creating thread 4
ERROR: return code from pthread_create() is 22 for thread 4
In main(), creating thread 5
ERROR: return code from pthread_create() is 22 for thread 5
Program received signal SIGSEGV, Segmentation fault. 0xb7fb4d8a in
pthread_join (threadid=76038327, thread_return=0x0)
at pthread_join.c:46 46 pthread_join.c: No such file or directory.
And here is my code:
#include <stdlib.h>
#include <stdio.h>
#include <strings.h>
#include <errno.h>
#include <pthread.h>
#include <unistd.h>
#define SBUFSIZE 1025
char errorstr[SBUFSIZE];
FILE* inputfp[5];
void* f(void* inpFile) {
fprintf(stderr, "%s\n", (char*)inpFile);
return NULL;
}
int main (int argc, char* argv[]) {
int i;
/* Thread Variables */
pthread_attr_t attr;
pthread_t *th[argc-2]; //one thread for each input file
/* allocate memory for the threads */
for (i = 0; i < (argc-2); i++) {
th[i] = (pthread_t *) malloc(sizeof(pthread_t));
inputfp[i] = fopen(argv[i], "r");
if (!inputfp[i]) {
sprintf(errorstr, "Error Opening Input File: %s", argv[i]);
perror(errorstr);
}
}
/* Create one thread for each input file */
for (i = 1; i < (argc - 1); i++) {
fprintf (stderr, "In main(), creating thread %1d\n", i);
int rc = pthread_create (th[i], &attr, f, inputfp[i-1]);
if (rc) {
printf("ERROR: return code from pthread_create() is %d for thread %d\n",
rc, i);
}
}
/* wait for the threads to finish */
for (i = 1; i < (argc - 1); i++) {
pthread_join(*th[i], 0);
}
return EXIT_SUCCESS;
}
I'm missing something, but I don't know what. Can anyone help? Thank you!
EDIT: Here is how I changed the code per the suggestion from Joachim Pileborg. I'm still getting error 22 returning from pthread_create(), but the SIGSEGV error on pthread_join is no longer occurring.
Anyone have any suggestions about how I can get the pthread_create() to return 0 (indicating a successful thread creation)? Thanks again!
int main (int argc, char* argv[]) {
int i;
/* Thread Variables */
pthread_attr_t attr;
pthread_t *th[argc-2]; //one thread for each input file
/* allocate memory for the threads */
for (i = 0; i < (argc-2); i++) {
th[i] = (pthread_t *) malloc(sizeof(pthread_t));
printf("%s\n", argv[i+1]);
inputfp[i] = fopen(argv[i+1], "r");
if (!inputfp[i]) {
sprintf(errorstr, "Error Opening Input File: %s", argv[i]);
perror(errorstr);
}
}
/* Create one thread for each input file */
for (i = 0; i < (argc - 2); i++) {
fprintf (stderr, "In main(), creating thread %1d\n", i);
int rc = pthread_create (th[i], &attr, f, inputfp[i]);
if (rc) {
printf("ERROR: return code from pthread_create() is %d for thread %d\n",
rc, i);
}
}
/* wait for the threads to finish */
for (i = 0; i < (argc - 2); i++) {
pthread_join(*th[i], 0);
}
return EXIT_SUCCESS;
}
You have one loop where you loop from zero to argc - 3, and uses the correct indexes (zero to "size of array minus one".
Then you have two loops where you loop from one to argc - 2, and use indexes from one to "size of array".
You should use the same loop as the first one in all three places.
I am trying to create a thread and from what I remember this should be the right way to do it:
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#define NUM_THREADS 5
int SharedVariable =0;
void SimpleThread(int which)
{
int num,val;
for(num=0; num<20; num++){
if(random() > RAND_MAX / 2)
usleep(10);
val = SharedVariable;
printf("*** thread %d sees value %d\n", which, val);
SharedVariable = val+1;
}
val=SharedVariable;
printf("Thread %d sees final value %d\n", which, val);
}
int main (int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
for(t=0; t< NUM_THREADS; t++){
printf("In main: creating thread %ld\n", t);
rc = pthread_create(&threads[t], NULL, SimpleThread, (void* )t);
if (rc){
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
/* Last thing that main() should do */
pthread_exit(NULL);
}
And the error that I'm getting is this one:
test.c: In function ‘main’: test.c:28: warning: passing argument 3 of
‘pthread_create’ from incompatible pointer type
/usr/include/pthread.h:227: note: expected ‘void * (*)(void *)’ but
argument is of type ‘void (*)(int)’
I cannot change the SimpleThread function so changing the type of the parameter is not an option even though I already tried and it didn't work either.
What am I doing wrong?
SimpleThread should be declared as
void* SimpleThread(void *args) {
}
When you pass parameters to your thread, it is best to define a struct for them, pass a pointer to that struct as void*, and cast back to the right type inside the function.
Here's a compiling and "working" version of your program, although I have to admit to not knowing exactly what it's doing. For the critics in the audience, I apologize in advance for the pthread_join loop at the end.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#define NUM_THREADS 5
struct my_thread_info {
long which;
};
int SharedVariable = 0;
void *SimpleThread(void *data)
{
int num, val;
struct my_thread_info *info = data;
for (num = 0; num < 20; num++) {
if (random() > RAND_MAX / 2)
usleep(10);
val = SharedVariable;
printf("*** thread %ld sees value %d\n", info->which, val);
SharedVariable = val + 1;
}
val = SharedVariable;
printf("Thread %ld sees final value %d\n", info->which, val);
free(info);
return NULL;
}
int main(int argc, char *argv[])
{
pthread_t threads[NUM_THREADS];
int rc;
long t;
struct my_thread_info *info;
for (t = 0; t < NUM_THREADS; t++) {
printf("In main: creating thread %ld\n", t);
info = malloc(sizeof(struct my_thread_info));
info->which = t;
rc = pthread_create(&threads[t], NULL, SimpleThread, info);
if (rc) {
printf("ERROR; return code from pthread_create() is %d\n", rc);
exit(-1);
}
}
for (t = 0; t < NUM_THREADS; t++) {
pthread_join(threads[t], NULL);
}
}