Named Semaphores in child processes confusing me - c

I have this very simple program to test out named semaphores:
#include <stdio.h>
#include <stdlib.h>
#include <semaphore.h>
#include <sys/ipc.h>
#include <unistd.h>
#include <sys/shm.h>
#include <fcntl.h>
sem_t thing;
void processOne() {
sleep(1);
int l;
sem_getvalue(&thing, &l);
printf("processOneThing: %d\n", l);
}
void processTwo(){
sem_wait(&thing);
printf("done");
}
int main(int argc, char **argv) {
int pidOne, pidTwo;
thing = *sem_open("/testest", O_CREAT|O_EXCL,0777,1);
pidTwo=fork();
if(pidTwo==0){
processTwo();
}
else{
pidOne=fork()
if(pidOne==0){
processOne();
}
else{
}
wait(&pidTwo);
wait(&pidOne);
}
sem_unlink("/testest");
sem_close(&thing);
}
The output is:
doneprocessOneThing: 1
Which means that the second process decremented the semaphore however the value of it in the first child process is still 1...
I have no idea what I am doing wrong and I looked at the named semaphore documentation and could not find much that could help me with this issue.
I'm compiling using:
gcc test.c -pthread
Any and all help would be much appreciated.

First, the code is missing a ; at end of this line:
else{
pidOne=fork() <------ here
if(pidOne==0){
processOne();
}
And it fails to #include<sys/wait.h> for wait() prototype. But correcting these issues I get the same output as you. So what is happening? The issue is with how you created the semaphore:
sem_t thing;
...
thing = *sem_open("/testest", O_CREAT|O_EXCL,0777,1);
The return from sem_open is the address of the created semaphore. But you are dereferencing that address and placing a copy of the contents into your variable thing. That means thing isn't actually the semaphore you created, but just a copy of the struct holding state information. The upshot is that interacting with thing in your code isn't actually interacting with what you intended. (In fact, you might get some indication that something isn't right if you check the return values on sem_wait() and sem_getvalue().)
If you instead make thing a pointer to the semaphore and interact with that, you get the following output:
done
processOneThing: 0
which is I think what you expected to see. You can try the corrected code here:
Runnable corrected code

Related

Sleep() function in C not working on hp non-stop

I am trying something in C on hp-nonstop(tandem),
As part my task is to wait for sometime.
I try to use the
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main()
{
int i;
for(i=0;i<10;i++)
{
printf("Something");
sleep(5);
printf("Something");
fflush(stdout);
}
}
It's compiling without any problem,
While running it is giving ABENDED: each time different no.
The result calling sleep() from guardian environment is undefined. That might be leading to ABEND that you mentioned. If you want to wait for some time in guardian hp-nonstop environment, you should call DELAY(). It takes centi-seconds as arguments. So if you want to add delay of 5 seconds, you should call it as DELAY (500). You also need to include the header #include<cextdecs(DELAY)>

Reading and writing into the same file using a named pipe in C

More specifically, the program is supposed to emulate the bash command cat file| grep $keyword > file.
What I've done is: In the parent I read every character from the file and format them into lines which I then send to the named pipe, then in the child write the lines containing the keyword into the original file.
However, I receive a segmentation fault error when attempting to read the second character from the original file, which I assume is because the parent is waiting for the child to write in the original file instead of instead of reading the contents of said file.
Any help with the implementation/explanation of why exactly the error occurs would be great.
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <signal.h>
#include <errno.h>
char key[20], *c,line[40];
int fd,fd_r,fd_w,fd_fr,fd_fw,counter=0;
int main(){
pid_t pid;
mkfifo("fifo1",0777);
fgets(key,10,stdin);
int k=0;
if ((pid=fork()) < 0)
perror("err_fork");
if(pid){ //PARENT
printf("%d\n",fd_r=open("prog.c",O_RDONLY));
printf("%d\n",fd_fw=open("fifo1",O_WRONLY));
while(read(fd_r,c,1)){
line[k++]=(*c);
while(read(fd_r,c,1) && ((*c)!='\n'))
line[k++]=(*c);
line[k]=0;
write(fd_fw,line,strlen(line)+1);
memset(line,0,sizeof(line));
}
close(fd_r);
close(fd_fw);
}
else{ //CHILD
printf("%d\n",fd_w=open("prog.c",O_WRONLY));
printf("%d\n",fd_fr=open("fifo1",O_RDONLY));
while(read(fd_fr,line,sizeof(line))){
c=strstr(line,key);
if(c)
write(fd_w,line,strlen(line)+1);
}
close(fd_w);
close(fd_fr);
}
unlink("fifo1");
}
You're segfaulting because you're trying to read a byte into c. However, c is an uninitialized global pointer and thus it's equal to NULL. Trying to read data at that location is therefore an invalid use of memory.
What you do instead is declare
char c;
and then
read(fd_r,&c,1)

C Why is the # of threads created in my code inconsistent?

The goal of my assignment is to create a loop to spawn 5 threads with integer arguments 0 through 4. I have 3 files: thread_demo.c that contains the main function, worker.c that contains the function to compute square of the argument, and header.h to keep the 2 files together.
thread_demo.c
#include "header.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <readline/readline.h>
#define NUM_THREADS 5
#define PROMPT_SIZE 5
int main(){
pthread_t threads[NUM_THREADS];
pthread_attr_t pthread_attributes;
int *prompt;
scanf("%d", &prompt);
for(int i = 0; i < NUM_THREADS; i++){
pthread_create(&threads[i], &pthread_attributes, &worker, (void *) prompt);
}
}
worker.c
#include "header.h"
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
void *worker(void * num){
int *input;
input = (int*) &num;
// Calculate square
int output = *input * *input;
printf("The square of %d", *input);
printf(" is %d.\n", output);
pthread_exit(NULL);
}
I have no compile errors, but the number of threads my code spawns is inconsistent. The pictures shown are my outputs from entering "5" 3 different times in which I have not made changes to the code. I'm not sure what causes this, I know I'm missing something but I don't know what it is.
I also have to make "the main thread wait until all threads have completed", which is confusing to me. When I spawn the 5 threads, how do I know which is the main thread?
I've never wrote code related to processes and threads so I'm completely lost. Any help would be greatly appreciated!
Your program is probably exiting before all your threads are complete. This would explain why you see different outputs on different runs: sometimes your program exits more or less quickly allowing less or more of the work to complete.
You need to keep your program from exiting (returning from main()) until all your thread are finished. To do this, you can use pthread_join for each of the threads. Add after you create all the threads:
for(int i = 0; i < NUM_THREADS; i++) {
pthread_join(threads[i]);
}
ptread_join will block (stop execution at that line) until the thread has terminated.
From the docs:
The pthread_join() function waits for the thread specified by thread
to terminate. If that thread has already terminated, then
pthread_join() returns immediately. The thread specified by thread
must be joinable.
http://man7.org/linux/man-pages/man3/pthread_join.3.html

redirect input using open() and close()

I'm trying to understand how the I/O between processes mechanism works.
I have tried to run this code:
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
...
char *const paramList[] = {"/bin/cat"};
close(0);
open("./my_file", O_RDONLY);
execv("/bin/cat",paramList);
...
but got nothing going on. (it compiles, though)
what did I do wrong and what does my code do?
Per the docs for execv:
The array of pointers must be terminated by a NULL pointer.
Thus, add NULL to the end of paramList.
If you're still having trouble, make sure to check the return values from all syscalls, and see if any of your calls are failing.

seteuid() not working. Reason?

I'm completely new to C and I use it very rarely. This time i need it for a university project. I have to write a small c app that tests some modifications we made on the Linux kernel (on the scheduler).
Inside the script I'd like to switch to another user to see the distribution of CPU times among the different users. So I start my small C prog with root rights (i.e. with sudo ./myapp). Inside the prog - after I performed some operations which need root rights - I would like to switch back to another uid by calling seteuid(1000) or setuid(1000) where 1000 is the ID of an existing user (the one I used to log on). However the call doesn't seem to have any effect, it doesn't throw any exception neither.
Here's a sample I wrote, just to test the uid switching:
#define _POSIX_SOURCE
#include <pwd.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <unistd.h>
#include <string>
#include <time.h>
using namespace std;
int main(int argc, char *argv[])
{
int uid;
struct passwd *p;
if ((p = getpwuid(uid = getuid())) == NULL){
perror("getpwuid() error");
exit(1);
}
printf("***************************************\n");
printf("Executing user: %s (%d)\n", p->pw_name, p->pw_uid);
printf("***************************************\n");
seteuid(1000);
if ((p = getpwuid(uid = getuid())) == NULL){
perror("getpwuid() error");
exit(1);
}
printf("***************************************\n");
printf("Executing user: %s (%d)\n", p->pw_name, p->pw_uid);
printf("***************************************\n");
return 0;
}
Does anyone know why it won't work?? Any help is highly appreciated! Thx
//Edit:
Corrected code as mentioned by chsh
I think it is working just fine, there's just a problem with the logic in the code because you're capturing the value of getuid() into the passwd struct, and then just displaying it twice without retrieving it again after calling seteuid().

Resources