Passing char[N] as thread argument in c? - c

Heres my code:
void *PrintLine(void *line)
{
printf("Line: #%s\n", (char *)line);
pthread_exit(NULL);
}
int main (int argc, char *argv[])
{
char line[80];
while(fgets(line,sizeof(line),fp))
{
pthread_create(&threads[rt], NULL, PrintLine, (void*)line);
}
fclose(fp);
}
Please dont tell me that running a thread only to print a file line doesn't make sense, I removed a lot of code so its easier to read and understand my problem.
As you would guess this code doesn't work, what should I do to be able to print/use "line" inside the thread?

You're passing a pointer to line to the newly created thread, when your thread gets around to use line , perhapse fgets have written something else to it. Or perhaps it's in the middle of writing something when your thread accesses it.
You can pass a copy of the line you've read, remember to free() it when you're done with it inside you thread.
char *copy_of_line = strdup(line);
if(copy_of_line)
pthread_create(&threads[rt], NULL, PrintLine, copy_of_line);

You need pthread_join(3) in the main thread to wait for completion of each thread you spawned. Otherwise the main thread might end the process before other threads have a chance to do the printing (and also to make sure the stack memory you point spawned threads to is still in scope).
Edit:
Then post "real" code, or at least "working" code. We are not mind readers.
Another obvious error is that main threads overrides the buffer the other threads are supposed to be printing. There's no guarantee that at some point the string in that buffer is not zero-terminated. You really need to make a copy in the main thread before giving it to other threads.

Two immediately obvious problems:
you only have instance of line (think about it)
there is no guarantee that printf is thread-safe

Your problem is that all your threads use the same line buffer so a new line might be read before the other one is printed.

Related

Where does the process start to execute after fork()

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
int main(void) {
for (int i = 1; i < 4; i++) {
printf("%d", i);
int id = fork();
if (id == 0) {
printf("Hello\n");
exit(0);
} else {
exit(0);
}
}
return 0;
}
For this code, it prints 11Hello on my computer. It seems counter-intuitive to me because "1" is printed twice but it's before the fork() is called.
The fork() system call forks a new process and executes the instruction that follows it in each process parallelly. After your child process prints the value of i to the stdout, it gets buffered which then prints the value of 'i' again because stdout was not flushed.
Use the fflush(stdout); so that 'i' gets printed only once per fork.
Alternately, you could also use printf("%d\n", i); where the new line character at the end does the job.
Where does the process start to execute after fork()
fork() duplicates the image of the process and it's context. It will run the next line of code pointed by the instruction pointer.
It seems counter-intuitive to me because "1" is printed twice but it's before the fork() is called.
Read printf anomaly after "fork()"
To begin with, the for loop is superfluous in your example.
Recall that the child copies the caller's memory(that of its parent) (code, globals, heap and stack), registers, and open files. To be performant or there may be some other reason, the printf call may not flush the buffer and put the things passed to that except for some cases such as appending new-line-terminator.
Before forking, the parent(main process) is on the way.
Let's assume we're on a single core system and the child first preempts the core.
1 is in the buffer because its parent put it into that before forking. Then, the child reaches second print statement, a caveat here is that the child can be orphaned at that time(no matter for this moment), passing "Hello\n" string including new-line character giving rise to dump the buffer/cache(whatever you call.) Since it sees \n character, it flushes the buffer including prior 1 added by its parent, that is 11Hello.
Let's assume the parent preempts the core at first,
It surrenders after calling exit statement, bringing on the child to be orphaned, causing memory leak. After that point, the boss(init possessing process id as 1) whose newly name I forget(it may be sys-something) should handle this case. However, nothing is changed as to the printing-steps. So you run into again 11Hello except if not the buffer is flushed automagically.
I don't have much working experience with them but university class(I failed at the course 4 times). However, I can advise you whenever possible use stderr while coping with these tings since it is not buffered, in lieu of stdout or there is some magical way(I forget it again, you call it at the beginning in main()) you can opt for to disable buffering for stdout as well.
To be more competent over these topics, you should glance at The Linux Programming Interface of Michael Kerrisk and the topics related to William Pursell,
Jonathan Leffler,
WhozCraig,
John Bollinger, and
Nominal Animal. I have learnt a plethora of information from them even if the information almost wholly is useless in Turkey borders.
*Magic means needing a lot of details to explain.

Is it a leak if memory isn't freed in a child process before exit?

There are similar question all over and one which is closes is from this stack exchange site. But even tho I learned a lot reading them none of them a exactly answer my question.
Here is the question, say I have this program (it is a very simplified version)
inline void execute(char *cmd)
{
int exitstat = 0;
//lots of other thins happed
exitstat = execve(cmd, cmdarg, environ);
free(cmd), free(other passed adress); ## DO I NEED THIS, since I am already about to exit
_exit (exitstat);
}
int main(void)
{
int childstat;
char *str = malloc(6); //I also have many more allocated space in heap in the parent process
strcpy(str, "Hello");
pid_t childid = fork() //creat a child process, which will also get a copy of all the heap memories even tho it is CoW.
if (childid < 0)
exit(-1);
if (child == 0)
{
execute(str);
}
else
{
wait(&childstat);
free(str);
}
//do somethign else with str with other functions and the rest of the program
}
In this program, the parent process does its thing for a while, allocates a lot of process in the heap, free some, keep other for later and at some point it wants to execute some command, but it doesn't want to terminate, so it creates a child to do its biting.
The child then calls another function which will do some task and in the end use execve to execute the command passed to it. If this was successful there would be no problem, since the executed program will handle all the allocated spaces, but if it failed the child exits with a status code. The parent waits for the child to answer, and when it does it moves on to its next routine. The problem here is that when the child fails to execute all the heap data remains allocated, but does that matter? since,
it is about to be exited int he next line,
Even though I am getting started with this, I have learned that a new process is created during fork, so the memory leak shouldn't affect the parent since the child is about to die.
If my assumption is correct and this leaks doesn't actually matter, why does valgrind lament about them?
Would there be a better way to free all the memories in the child heap with out actually passing all the memores (str, and the others in this example) to the execute function and laboriously call free each time? does kill() have a mechanism for this?
Edit
Here is working code
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <string.h>
inline void execute(char *cmd)
{
extern char **environ;
int exitstat = 0;
char *cmdarg[2];
cmdarg[0] = cmd;
cmdarg[1] = NULL;
exitstat = execve(cmd, cmdarg, environ);
free(cmd);
_exit (exitstat);
}
int main(void)
{
int childstat;
char *str = malloc(6);
pid_t childid;
strcpy(str, "Hello");
childid = fork();
if (childid < 0)
exit(-1);
if (childid == 0)
{
execute(str);
}
else
{
wait(&childstat);
free(str);
}
return (0);
}
When there is a free inside the child process here is valgrinds result.
When run with the free inside the child process is commented.(#free(cmd) in the execute function).
As you might see there is no overall error () since this programm is short lived. But in my real program which has an infinite loop every problem in the child () matters. So I was asking if I be worried by this leaked memories in this child process just before exiting and hunt them down or just leave them as they are in another virtual space and they are cleaned as their processes exit (but in that case why is valgrind still complaining about them if their corresponding process clean them during exit)
exitstat = execve(cmd, cmdarg, environ);
free(cmd), free(other passed adress);
If successful, execve does not return. No code is executed after it, the execution is terminated and the cmd process is started. All memory hold by current process is freed anyway by the operating system. The code free(cmd), free(other passed adress); will not execute if execve call is successful.
The only case where those liens could be relevant are in case of execve error. And in case execve returns with an error, yes, you should free that memory. I much doubt most programs with execve actually do that and I believe they would just call abort() after failed execve call.
inline void execute(char *cmd)
Please read about inline. inline is tricky. I recommend not use it, forget it exists. I doubt the intention here is to make an inline function - there is no other function the compiler can choose from anyway. After fixing typos in code, I could not compile the code because of undefined reference to execute - inline has to be removed.
The problem here is that when the child fails to execute all the heap data remains allocated, but does that matter?
Ultimately it depends on what do you want to do after the child fails. If you want to just call exit and you do not care about memory leaks in such case, then just don't care and it will not matter.
I see glibc exec*.c functions try to avoid dynamic allocation as much as possible and use variable length arrays or alloca().
If my assumption is correct and this leaks doesn't actually matter, why does valgrind lament about them?
It doesn't. If you correct all the mistakes in your code, then valgrind will not "lament" about memory leaks before calling execve (well, unless the execve call fails).
Would there be a better way to free all the memories in the child heap with out actually passing all the memores (str, and the others in this example) to the execute function and laboriously call free each time?
"Better" will tend to be opinion based. Subjectively: no. But writing/using own wrapper around dynamic allocation with garbage collector to free all memory is also an option.
does kill() have a mechanism for this?
No, sending a signal seems unrelated to freeing memory.
There is no simple solution.
On termination, the OS will free all memory for a process. That means that you don't have to free everything. However, for memory that is no longer needed it is usually best to free it as soon as possible. That leaves things like buffers that could potentially be used right up to the last moment before termination.
Reasons to free memory.
There's only one that I can think of. If you have a large number of blocks in use at the end it can be difficult to sort the wheat from the chaff. Either you end up with enormous logs that no-one looks at, or you have to maintain a suppression file. Either way you risk overlooking genuine issues.
Reasons not to free memory
Small performance gain
It can be quite difficult sometimes to free everything. For instance if you use putenv() then knowing whether the string was added (and needs freeing) or replaced (must not be freed) is a bit tricky.
If you need to use atexit() to free things, then there is a limit on the number of functions that you can call via atexit(). That might be a problem if you have many things being freed in many modules.
My advice is try to free most things but don't sweat it or you'll get bitten by the law of diminishing returns. Use a suppression file judiciously for the few percent that are tricky to free.

is it safe to write to a file in another thread?

I do not know, if this is ok, but it compiles:
typedef struct
{
int fd;
char *str;
int c;
} ARG;
void *ww(void *arg){
ARG *a = (ARG *)arg;
write(a->fd,a->str,a->c);
return NULL;
}
int main (void) {
int fd = open("./smf", O_CREAT|O_WRONLY|O_TRUNC, S_IRWXU);
int ch = fork();
if (ch==0){
ARG *arg; pthread_t p1;
arg->fd = fd;
arg->str = malloc(6);
strcpy(arg->str, "child");
arg->c = 6;
pthread_create( &p1, NULL, ww, arg);
} else {
write(fd, "parent\0", 7);
wait(NULL);
}
return 0;
}
I am wait()int in parent, but I do not know if I should also pthread_join to merge threads or it is implicitly by wait(). However is it even safe to write to the same file in two threads? I run few times and sometimes output was 1) parentchild but sometimes only 2) parent, no other cases - I do not know why child did not write as well when parent wait()s for it. Can someone please explain why these outputs?
You need to call pthread_join() in the child process to avoid potential race conditions during the child process’s exit sequence (for example the child process can otherwise exit before its thread gets a chance to write to the file). Calling pthread_join() in the parent process won’t help,
As for the file, having both processes write to it is safe in the sense that it won’t cause a crash, but the order in which the data is written to the file will be indeterminate since the two processes are executing concurrently.
I do not know, if this is ok, but it compiles:
Without even any warnings? Really? I suppose the code you are compiling must include all the needed headers (else you should have loads of warnings), but if your compiler cannot be persuaded to spot
buggy.c:30:15: warning: ‘arg’ may be used uninitialized in this
function [-Wmaybe-uninitialized]
arg->fd = fd;
^
then it's not worth its salt. Indeed, variable arg is used uninitialized, and your program therefore exhibits undefined behavior.
But even if you fix that, after which the program can be made to compile without warnings, it still is not ok.
I am wait()int in parent, but I do not know if I should also
pthread_join to merge threads or it is implicitly by wait().
The parent process is calling wait(). This waits for a child process to terminate, if there are any. Period. It has no implications for the behavior of the child prior to its termination.
Moreover, in a pthreads program, the main thread is special: when it terminates, the whole program terminates, including all other threads. Your child process therefore suffers from a race condition: the main thread terminates immediately after creating a second thread, without ensuring that the other thread terminates first, so it is undefined what, if any, of the behavior of the second thread is actually performed. To avoid this issue, yes, in the child process, the main thread should join the other one before itself terminating.
However
is it even safe to write to the same file in two threads?
It depends -- both on the circumstances and on what you mean by "safe". POSIX requires the write() function to be thread-safe, but that does not mean that multiple threads or processes writing to the same file cannot still interfere with each other by overwriting each other's output.
Yours is a somewhat special case, however, in that parent and child are writing via the same open file description in the kernel, the child having inherited an association with that from its parent. According to POSIX, then, you should see both processes' output (if any; see above) in the file. POSIX provides no way to predict the order in which those outputs will appear, however.
I run few
times and sometimes output was 1) parentchild but sometimes only 2)
parent, no other cases - I do not know why child did not write as well
when parent wait()s for it. Can someone please explain why these
outputs?
The child process can terminate before its second thread performs its write. In this case you will see only the parent's output, not the child's.

Print in single Pthread

I'm trying to implement a program using Pthreads in C. Now, I've tried to let a single thread print "Hi":
void * generator(void *arguments){
printf("Hi");
return NULL;
}
int main(int argc, const char* argv[]){
pthread_create(&threads_ids[0], NULL, &generator, NULL);=
}
This doesn't work and doesn't print anything. However, when I put the creation of the pthread in a for loop it does print "Hi", but at each execution the occurrence differs.
Is this normal behaviour, and if so; how can I fix it? Thanks in advance!
It's because your main thread returns and thus exits the process. It means the thread you created never gets a chance to run.
Unlike just returning from main(), calling pthread_exit(0) from main(), will let the other thread continue executing.
Alternatively, you can wait for the thread to complete execution by calling pthread_join() on the thread you created.
When you execute in a loop, probably some of the threads you create gets executed before main thread exits, and thus appears to "work" (prints some Hi).
But it does have the same problem as the code you posted.

Running Concurrent Threads in C?

I'm testing the behavior of running concurrent threads in C, with a thread function that runs infinitely. My question is why doesn't, in the below code, "HELLO!!!" gets printed? I thought pthread_create() is called and then immediately it goes to the next iteration of the loop, why is the code waiting for the 1st pthread_create() to finish? Aren't multiple threads supposed to be running concurrently?
void main(int argc, char **argv)
{
pthread_t tid;
int i;
//Create 4 inf threads
for (i=0;i< 4;i++)
{
//printf("hello!\n");
//pthread_create(&tid, NULL, thread_incr, (void *)i);
pthread_create(&tid, NULL, t_nostop, (void *)i);
printf("HELLO!!!"); //This linen is NEVER printed!!
}
pthread_exit(NULL);
}
void* t_nostop(void * argp)
{
int i=1;
int t_num=(int) argp;
while(i==1){t_num++;}
}
Multiple threads are supposed to run concurrently. This should be happening in your code.
I'd guess that the printf calls are executed but don't generate output immediately. Console output may be line buffered, so will only be displayed when you print a newline or flush.
Try either adding \n at the end of the string you print or adding fflush(stdout) after the printf.
Edit: A comment asked about line buffering...
Line buffering happens when the standard C library decides that console writes are relatively expensive and should only be attempted for coherent blocks of text. One easy definition for a coherent block is a line. While it is waiting for a newline to be entered, the C lib stores the contents of printf calls in a block of memory, appending subsequent printfs
From my understanding on pthreads, you haven't actually started the thread yet. Try, after the pthread_create, adding pthread_join(tid, NULL); and see if it works.

Resources