Alternate Without Semaphores - linux

The program below creates two processes.
The parent process prints the numbers from 0 to 9, while the
child process prints the characters from A to J.
How can I make it alternate the printing using only signals? so no using semaphores or any IPCs.
#include <stdio.h>
int main()
{
int i = 0;
if (fork() == 0) /* Child process */
{
for (i = 0; i < 10; i++) {
printf("%c\n", i + 65);
}
} else /* Parent process */
{
for (i = 0; i < 10; i++) {
printf("%d\n", i);
}
}
}

I figured it out.
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <errno.h>
#include <sys/wait.h>
#include <signal.h>
int main()
{
int i=0;
int status;
int childPID = fork();
if (childPID == 0) /* Child process */
{
for(i=0;i<10;i++){
printf("%c\n",i+65);
kill(getpid(), SIGSTOP);
}
} else /* Parent process */
{
for(i=0;i<10;i++) {
waitpid(childPID,&status,WUNTRACED);
printf("%d\n",i);
kill(childPID, SIGCONT);
}
}
}

Related

Handler callback is not calling properly in Signals for SIGCHLD

I registered handler for SIGCHLD stop/exit and i am creating 4 child i am modifying global variable in it works fine as copy on write(COW). But handler function is not called for 4 child. when i print the global variable in parent, its value is 18 as i am expecting 21.
[Attached the output of image]
[1]: https://i.stack.imgur.com/7QOze.png
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <signal.h>
#include <stdlib.h>
#include <sys/wait.h>
#define N 4
int val = 9;
void handler(int sig)
{
val += 3;
printf("Inside handler getpid() = %d val = %d\n", getpid(), val);
return;
}
int main()
{
pid_t pid;
int i;
signal(SIGCHLD, handler);
for (i = 0; i < N; i++)
{
if ((pid = fork()) == 0)
{
val -= 3;
printf("Inside child getpid() = %d val = %d\n", getpid(), val);
exit(0);
}
}
for (i = 0; i < N; i++)
{
waitpid(-1, NULL, 0);
//printf("Inside parent getpid() = %d val = %d\n", getpid(), val);
}
printf("val = %d\n", val);
}

Using cat and execvp

Trying to understand why this section of code using the cat command isn't working with execvp in C.
char *in[5] ={"cat", "file1.txt", ">>", "file2.txt", 0};
execvp(in[0], in);
When I run it displays the contents of file1.txt but then says:
cat: >> No such file or directory.
Then displays the contents of file2.txt
Why wouldn't it recognize the >> operator in this instance?
You can read the "man tee" command which it read from standard input and write to standard output and files. You could achieve this with below example.
#include <sys/types.h>
#include <sys/wait.h>
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
/*
Implementation of below command:
cat file1.txt > file2.txt
*/
char *cmd1[] = { "/bin/cat", "file1.txt", 0 };
char *cmd2[] = { "tee", "file2.txt", 0 };
static void sigchld_hdl (int sig)
{
int status;
while (waitpid(-1, &status, 0) > 0) {
if(WIFEXITED(status))
printf("Child exited with code %d\n", WEXITSTATUS(status)); }
}
int runcmd(int pfd[])
{
int i=0;
switch (fork()) {
case -1:
perror ("fork");
return 1;
case 0:
dup2(pfd[0], 0);
close(pfd[1]); /* the child does not need this end of the pipe */
execvp(cmd2[0], cmd2);
perror(cmd2[0]);
exit(10);
default: /* parent */
dup2(pfd[1], 1);
close(pfd[0]); /* the parent does not need this end of the pipe */
execvp(cmd1[0], cmd1);
perror(cmd1[0]);
}
sleep(1);
}
int main (int argc, char *argv[])
{
struct sigaction act;
int fd[2];
pipe(fd);
memset (&act, 0, sizeof(act));
act.sa_handler = sigchld_hdl;
if (sigaction(SIGCHLD, &act, 0)) {
perror ("sigaction");
return 1;
}
runcmd(fd);
return 0;
}

trying to use pipe(2) with the sort unix tool but not working

I have been struggling to find what I'm doing wrong and I can't seem to find the issue. When I compile the code below, I get an I/O error.
e.g: /usr/bin/sort: read failed: -: Input/output error
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
int main(int argc, char **argv, char **envp)
{
int fd[2];
pid_t pid;
pipe(fd);
pid = fork();
if (pid == -1) {
exit(EXIT_FAILURE);
}
if (pid == 0) { /* child */
char *exe[]= { "/usr/bin/sort", NULL };
close(fd[0]);
execve("/usr/bin/sort", exe, envp);
}
else {
char *a[] = { "zilda", "andrew", "bartholomeu", NULL };
int i;
close(fd[1]);
for (i = 0; a[i]; i++)
printf("%s\n", a[i]);
}
return 0;
}
dup2(fd[0], 0) in the child.
dup2(fd[1], 1) in the parent.
close the other fd.

Linux - Syscall to Iterate over children threads

I am creating a syscall to return some information about a process and its children threads. I am testing this in Ubuntu 14.04. Here is the code that I have written:
#include <linux/list.h>
#include <linux/linkage.h>
#include <linux/sched.h>
#include <linux/uaccess.h>
#define NUM_THREADS 5
struct thread_info_prj {
int pid;
int nthreads;
int tid[NUM_THREADS];
};
asmlinkage void sys_threadinfo_prj(void *ptr)
{
struct task_struct *task;
struct thread_info_prj t_info;
struct list_head *list;
int num_threads = 0;
t_info.pid = current->pid;
list_for_each(list, &current->children) {
//task = list_entry(&p_task->children, struct task_struct, sibling);
task = list_entry(list, struct task_struct, sibling);
t_info.tid[num_threads] = task->pid;
num_threads++;
}
t_info.nthreads = num_threads;
copy_to_user(ptr, &t_info, sizeof(struct thread_info_prj));
}
This code is built into the kernel as a syscall , and tested with the following program.
#include <pthread.h>
#include <stdio.h>
#include <sys/syscall.h>
#include <errno.h>
#define NUM_THREADS 5
struct thread_info_prj {
int pid;
int nthreads;
int tid[NUM_THREADS];
};
void * thread_fn(void *ptr) {
printf("Im a thread!\n");
sleep(4);
pthread_exit(NULL);
}
int main() {
pthread_t threads[NUM_THREADS];
pthread_attr_t attr;
int i;
struct thread_info_prj t_info;
void *status;
pthread_attr_init(&attr);
//pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
for (i = 0; i < NUM_THREADS; i++)
pthread_create(&(threads[i]), &attr, thread_fn, NULL);
sleep(1);
syscall(352, &t_info);
//for (i = 0; i < NUM_THREADS; i++)
// pthread_join(threads[i], &status);
printf("PID: %d\n", t_info.pid);
printf("Num Threads: %d\n", t_info.nthreads);
for (i = 0; i < t_info.nthreads; i++) {
printf("Thread ID: %d\n", t_info.tid[i]);
}
printf("%s\n",strerror(errno));
return 0;
}
Unfortunately, the only output is the proper parent pid. Otherwise, it returns that there are no threads and does not print any additional PIDs. By adding a printk inside the for loop, I discovered that it never even enters the for loop. Any suggestions?
Thanks so much.

Multithread Directory and File Search

I am new to semaphores and the concepts of mutual exclusion. I am supposed to recursively text search in files through directories using multithreading. The number of threads is to be given by the user.
The issue with this code is it goes through one directory and then waits. I cannot figure out what is wrong.I am getting a segmentation fault error. Cannot figure out why is this happening.
#include <iostream>
#include <sys/wait.h>
#include <sys/types.h>
#include <pthread.h>
#include <string.h>
#include <unistd.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fstream>
#include <limits.h>
#include <stdlib.h>
#include <semaphore.h>
using namespace std;
#include <stdio.h>
int iDirectories=0;
pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
sem_t semaphore1;
char searchStringThread[PATH_MAX];
int directories=0;
class directoryQueue
{
private:
struct Node
{
char directoryPath[PATH_MAX];
Node *next;
};
Node *front;
Node *rear;
Node *nodeCount;
public:
directoryQueue(void)
{
front=NULL;
rear=NULL;
nodeCount=0;
}
void Enqueue(char array[PATH_MAX])
{
Node *newNode;
newNode=new Node;
strcpy(newNode->directoryPath,array);
newNode->next=NULL;
if(isEmpty())
{
front=newNode;
rear=newNode;
}
else
{
rear->next=newNode;
rear=newNode;
}
nodeCount++;
}
char * Dequeue(void)
{
Node *temp;
if (isEmpty())
cout << "Error ! Empty Queue "<<endl;
else
{
char *deque;
deque=new char[PATH_MAX];
strcpy(deque,front->directoryPath);
temp = front->next;
front = temp;
nodeCount--;
return deque;
}
}
bool isEmpty(void)
{
if(nodeCount)
return false;
else
return true;
}
void makeNull(void)
{
while(!isEmpty())
{
Dequeue();
}
}
~directoryQueue(void)
{
makeNull();
}
};
directoryQueue saveDirectory;
void *threadHandler(void *)
{
int thpath_length;
char thPath[PATH_MAX];
char saveITDirectory[PATH_MAX];
char itDirectory[PATH_MAX];
int threadCount;
struct dirent *iWalker;
DIR *iDirectory;
pthread_mutex_lock(&mutex);
threadCount=iDirectories++;
pthread_mutex_unlock(&mutex);
sem_wait(&semaphore1);
pthread_mutex_lock(&mutex);
strcpy(itDirectory,saveDirectory.Dequeue());
pthread_mutex_unlock(&mutex);
iDirectory=opendir(itDirectory);
if(iDirectory==NULL)
{
cout<<"Error"<<endl;
cout<<itDirectory<<" Cannot be Opened"<<endl;
exit(10000);
}
while((iWalker=readdir(iDirectory)) !=NULL)
{
if(iWalker->d_type==DT_REG)
{
strcpy(saveITDirectory,iWalker->d_name);
cout<<itDirectory<<"/"<<endl;
if (strcmp (saveITDirectory, "..") == 0 ||
strcmp (saveITDirectory, ".") == 0)
{
continue;
}
else
{
thpath_length = snprintf(thPath,PATH_MAX,"%s/%s",itDirectory,saveITDirectory);
cout<<thPath<<endl;
if (thpath_length >= PATH_MAX)
{
cout<<"Path is too long"<<endl;
exit (1000);
}
ifstream openFile;
openFile.open(thPath);
char line[1500];
int currentLine = 0;
if (openFile.is_open()) {
while (openFile.good()) {
currentLine++;
openFile.getline(line, 1500);
if (strstr(line, searchStringThread) != NULL){
cout<<thPath<<": "<<currentLine<<": "<<line<<endl;
cout<<"This was performed by Thread no. "<<threadCount<<endl;
cout<<"ID :"<<pthread_self();
}
}
}
openFile.close();
}
}
if (closedir (iDirectory))
{
cout<<"Unable to close "<<itDirectory<<endl;
exit (1000);
}
}
}
void walkThroughDirectory(char directory_name[PATH_MAX],char searchString[PATH_MAX])
{
DIR * directory;
struct dirent * walker;
char d_name[PATH_MAX];
int path_length;
char path[PATH_MAX];
directory=opendir(directory_name);
if(directory==NULL)
{
cout<<"Error"<<endl;
cout<<directory_name<<" Cannot be Opened"<<endl;
exit(10000);
}
while((walker=readdir(directory)) !=NULL)
{
strcpy(d_name,walker->d_name);
cout<<directory_name<<"/"<<endl;
if (strcmp (d_name, "..") == 0 ||
strcmp (d_name, ".") == 0)
{
continue;
}
else
{
path_length = snprintf(path,PATH_MAX,"%s/%s",directory_name,d_name);
cout<<path<<endl;
if (path_length >= PATH_MAX)
{
cout<<"Path is too long"<<endl;
exit (1000);
}
if(walker->d_type==DT_DIR)
{
pthread_mutex_lock(&mutex);
saveDirectory.Enqueue(path);
pthread_mutex_lock(&mutex);
sem_post(&semaphore1);
directories++;
walkThroughDirectory (path,searchString);
}
else if(walker->d_type==DT_REG)
{
ifstream openFile;
openFile.open(path);
char line[1500];
int currentLine = 0;
if (openFile.is_open()) {
while (openFile.good()) {
currentLine++;
openFile.getline(line, 1500);
if (strstr(line, searchString) != NULL)
cout<<path<<": "<<currentLine<<": "<<line<<endl;
}
}
openFile.close();
}
}
}
if (closedir (directory))
{
cout<<"Unable to close "<<directory_name<<endl;
exit (1000);
}
}
int main(int argc,char *argv[])
{
char * name;
cout<<"Total Directories "<< directories<<endl;
name=get_current_dir_name();
cout<<"Current Directory is: "<<name<<endl;
sem_init(&semaphore1,0,0);
strcpy(searchStringThread,argv[1]);
int number_of_threads=atoi(argv[3]);
pthread_t threads[number_of_threads];
walkThroughDirectory(argv[2],argv[1]);
pthread_mutex_lock(&mutex);
saveDirectory.Enqueue(argv[2]);
pthread_mutex_unlock(&mutex);
sem_post(&semaphore1);
for(int i=0;i<number_of_threads;i++)
{
pthread_create(&threads[i],NULL,threadHandler,NULL);
}
for(int j=0;j<number_of_threads;j++)
{
pthread_join(threads[j],NULL);
}
while(saveDirectory.isEmpty())
{
cout<<"Queue is Empty"<<endl;
cout<<"Exiting"<<endl;
exit(10000);
}
free(name);
cout<<"Total Directories "<< directories<<endl;
return 0;
}
There's a simple bug where you lock a mutex twice instead of unlocking it when you're done:
pthread_mutex_lock(&mutex);
saveDirectory.Enqueue(path);
pthread_mutex_lock(&mutex);
should be:
pthread_mutex_lock(&mutex);
saveDirectory.Enqueue(path);
pthread_mutex_unlock(&mutex);
Note: this isn't to say that there aren't other problems - just that this is probably your immediate problem.
The biggest problem is that it looks like you put directories on the saveDirectory queue (so another thread can pull it off to work on it), then go ahead an process that directory recursively in the thread that just put it on the queue. I think you'll need to give some more thought on how the work will be divided among the threads.
A couple of more minor comments:
you might want to consider using std::string if that's permitted. It should make some of your string handling simpler (you leak memory from the data returned from directoryQueue::Dequeue(), for example)
if the primary reason for the existence of the directoryQueue class is to hold work items for multiple threads, then maybe it should manage it's own mutex so callers don't need to deal with that complexity

Resources