I'm trying to solve my school project in C++. I have to create 15 processes and they have to run in order what means that processes run in this order 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 0. It work but when I try to remove semaphore from the memory I am getting error from semctl. On the end I use "semctl(semid, 0, IPC_RMID, 0" but I get error 22 which means EINVAL but it doesn't make sense and I try to remove semaphore from parrent process so I should have privileges to do that.
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <errno.h>
#include <sys/wait.h>
union semun {
int val;
struct semid_ds *buf;
ushort *array;
};
struct sembuf sops[1];
int semid;
int wait_sem(int index, int pid){
fprintf(stderr, "\n------- Proces %d do operation wait (-1) on semaphore %d\n",pid, index);
sops[0].sem_num = index;
sops[0].sem_op = -1;
sops[0].sem_flg = 0 ;
if (semop(semid, sops, 1)<0){
perror("semop fail wait");
return 1;
}
else
return 0;
}
int signal_sem(int index, int pid){
fprintf(stderr, "\n++++++ Proces %d vykonava operaciu signal (1) na semafore %d\n",pid,index);
sops[0].sem_num = index;
sops[0].sem_op = 1;
sops[0].sem_flg = 0;
if (semop(semid, sops, 1)<0){
perror("semop fail signal");
return 1;
}
else
return 0;
}
void createSem(key_t paKey, int paSemFlg, int paNsems)
{
printf ("uid=%d euid=%d\n", (int) getuid (), (int) geteuid ());
(semid = semget(paKey, paNsems, paSemFlg));
for (int i = 0; i < paNsems; ++i) {
semctl(semid, i, SETVAL, 0);
}
}
void kic()
{
printf("\naaaaaaaaaaaaaa\n");
}
int main() {
key_t key = 1234;
int semflg = IPC_CREAT | 0666;
int nsems = 15;
int semid;
fprintf(stderr, "%d=", sops);
createSem(IPC_PRIVATE, semflg, nsems);
if (semid == -1) {
perror("semget: semget failed");
return 1;
}
else
fprintf(stderr, "semget: semget sucess: semid = %d, parrent pid %d\n", semid, getpid());
int PROCESS_ID = 0;
pid_t PID;
for (int i = 1; i < nsems; i++) {
PID = fork();
if(PID == 0)
{
PROCESS_ID = i;
break;
}
}
if(PID == -1)
{
printf("\nPID ERROR");
}
if(PID != 0) //parrent
{
printf("\n\nparrent with ID %d", PROCESS_ID);
signal_sem(PROCESS_ID+1, PROCESS_ID);
wait_sem(PROCESS_ID, PROCESS_ID);
printf ("uid=%d euid=%d\n", (int) getuid (), (int) geteuid ());
printf("\nEND %d\n", getpid());
int s;
wait(&s);
if((semctl(semid, 0, IPC_RMID, 0))==-1)
{
int a = errno;
printf("\nERROR IPC_RMID %d\n", a);
}
}
if(PID == 0)//child
{
if(wait_sem(PROCESS_ID, PROCESS_ID) == 0){
printf("\nI am child with ID %d", PROCESS_ID);
int ID_NEXT_PROCESS = 1+PROCESS_ID;
if(ID_NEXT_PROCESS == nsems)
ID_NEXT_PROCESS = 0;
signal_sem(ID_NEXT_PROCESS, PROCESS_ID);
return 0;
}
}
return 0;
}
You have two semids. One in global scope, another local to main (which shadows global, you should see a warning). createSem only knows about global one, and initializes it. semctl is called directly by main, and is passed the local one, which is garbage.
Related
I want to setup an asynchronous bulk transfer to a callback routine but I never enter the callback routine. I changed the code to a synchronous transfer and it works. Please help me understand what I'm doing wrong with the asynchronous transfer. Below is the synchronous transfer
#include <stdio.h>
#include <libusb.h>
#define LB04_VID 4302
#define LB04_PID 60307
unsigned char in_buf[32];
void hexdump(unsigned char* data, int len)
{
int i;
for (i = 0; i < len; i++) printf("%02X ", data[i]);
puts("\n");
}
int main(int argc, char* argv[])
{
libusb_device** devs;
libusb_device_handle* dev_handle;
libusb_context* context = NULL;
size_t list;
int ret;
int iLen;
ret = libusb_init(&context);
if (ret < 0) {
perror("libusb_init");
return 1;
}
libusb_set_option(context, LIBUSB_OPTION_MAX);
list = libusb_get_device_list(context, &devs);
if (list < 0) {
perror("libusb_get_device_list");
return 1;
}
dev_handle = libusb_open_device_with_vid_pid(context, LB04_VID, LB04_PID);
libusb_free_device_list(devs, 1);
printf("found XHC-HB04 device\n");
if (dev_handle) {
if (libusb_kernel_driver_active(dev_handle, 0) == 1) {
libusb_detach_kernel_driver(dev_handle, 0);
}
ret = libusb_claim_interface(dev_handle, 0);
if (ret < 0) {
perror("libusb_claim_interface");
return 1;
}
ret = libusb_set_configuration(dev_handle, 1);
while (1) {
ret = libusb_bulk_transfer(dev_handle, (0x01 | LIBUSB_ENDPOINT_IN), in_buf, sizeof(in_buf), &iLen, 0);
hexdump((unsigned char*)&in_buf, iLen);
}
libusb_release_interface(dev_handle, 0);
libusb_close(dev_handle);
}
libusb_exit(context);
}
This loops forever like I want. However, when I try to use asynchronous transfer like the below, my callback never gets called. Please help as I'm stuck with what to try next.
#include <stdio.h>
#include <libusb.h>
#define LB04_VID 4302
#define LB04_PID 60307
unsigned char in_buf[32];
libusb_device** devs;
libusb_device_handle* dev_handle;
libusb_context* context = NULL;
struct libusb_transfer* transfer_in = NULL;
int setup_asynch_transfer(libusb_device_handle* dev_handle);
void hexdump(unsigned char* data, int len)
{
int i;
for (i = 0; i < len; i++)
printf("%02X ", data[i]);
puts("\n");
}
void cb_response_in(struct libusb_transfer* transfer)
{
printf("cb_response_in\n");
if (transfer->actual_length > 0)
hexdump((unsigned char*)&in_buf, transfer->actual_length);
setup_asynch_transfer(transfer->dev_handle);
}
int setup_asynch_transfer(libusb_device_handle* dev_handle)
{
int ret;
printf("setup_asynch_transfer\n");
transfer_in = libusb_alloc_transfer(0);
libusb_fill_bulk_transfer(transfer_in, dev_handle, (0x01 | LIBUSB_ENDPOINT_IN),
in_buf, sizeof(in_buf),
cb_response_in, NULL, 500); // no user data
return (ret = libusb_submit_transfer(transfer_in));
}
int main(int argc, char* argv[])
{
size_t list;
int ret;
ret = libusb_init(&context);
if (ret < 0) {
perror("libusb_init");
return 1;
}
libusb_set_option(context, LIBUSB_OPTION_MAX);
list = libusb_get_device_list(context, &devs);
if (list < 0) {
perror("libusb_get_device_list");
return 1;
}
dev_handle = libusb_open_device_with_vid_pid(context, LB04_VID, LB04_PID);
libusb_free_device_list(devs, 1);
printf("found XHC-HB04 device\n");
if (dev_handle) {
if (libusb_kernel_driver_active(dev_handle, 0) == 1) {
libusb_detach_kernel_driver(dev_handle, 0);
}
ret = libusb_claim_interface(dev_handle, 0);
if (ret < 0) {
perror("libusb_claim_interface");
return 1;
}
ret = libusb_set_configuration(dev_handle, 1);
ret = setup_asynch_transfer(dev_handle);
// Loop forever
while (1);
libusb_release_interface(dev_handle, 0);
libusb_close(dev_handle);
}
libusb_exit(context);
}
I made sure I could execute a bulk synchronous transfer and then converted the code to execute asynchronous transfer. I expected the callback routine to print the data and schedule another asynchronous routine while the main routine waited in a while loop forever.
I'm using libusb-1.0 and Microsoft Visual Studio Community 2022 on Windows 10.
I'm attempting to create a program that creates 2 child processes, and 4 pipes (I know this isn't ideal, but the spec for this specific assignment requires it). While it correctly sorts two of the 5 command line argument integers, the rest are just spat out as what I believe are uninitialized integers, I.E. 7 is printed out as 33234951.
I'm pretty new to pipes, and it's been a little hard to wrap my head around, so I believe this issue has to do with this and not some arbitrary error in code.
I was able to successfully get this done using only 1 parent and child, but as soon as I tried to implement multiple, things got dicey.
I have a lot of unused includes just from messing around with things in attempt to solve the problem.
#include <bits/stdc++.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
int main(int argc, char **argv) {
printf("Starting\n");
pid_t pid;
pid_t pid2;
int mypipe0[2];
int mypipe1[2];
int mypipe2[2];
int mypipe3[2];
pipe(mypipe0);
pipe(mypipe1);
pipe(mypipe2);
pipe(mypipe3);
/* Create the child process. */
pid = fork();
std::cout << "Fork " << pid << std::endl;
// Child: Sorts Array
if (pid == 0) {
printf("pid == (pid_t) 0 p2\n");
/* This is the child process.
Close other end first. */
close(mypipe0[1]);
char valuesArray[5];
for (int a = 0; a < 5; a++)
read(mypipe0[0], &valuesArray[a], sizeof(char));
printf("finish reading mypipe0");
std::sort(valuesArray, valuesArray + 5);
printf("sorted");
close(mypipe1[0]);
close(mypipe2[0]);
for (int a = 0; a < 5; a++) {
write(mypipe1[1], &valuesArray[a], sizeof(char));
write(mypipe2[1], &valuesArray[a], sizeof(char));
}
close(mypipe1[1]);
close(mypipe2[1]);
exit(0);
}
else if (pid > 1) {
std::cout << "pid == (pid_t) 1" << std::endl;
/* This is the parent process.
Close other end first. */
close(mypipe0[0]); // Closes reading
int valuesArray[5];
valuesArray[0] = atoi(argv[1]);
valuesArray[1] = atoi(argv[2]);
valuesArray[2] = atoi(argv[3]);
valuesArray[3] = atoi(argv[4]);
valuesArray[4] = atoi(argv[5]);
printf("Argv init");
for (int a = 0; a < 5; ++a)
write(mypipe0[1], &valuesArray[a], sizeof(char));
printf("wrote to pipe 1");
close(mypipe0[1]);
wait(NULL);
close(mypipe1[1]); // Closes writing
// char outputArray[6];
int sortedArray[5];
for (int a = 0; a < 5; ++a)
read(mypipe1[0], &sortedArray[a], sizeof(char));
// Printing Array]
for (int a = 1; a < 5; ++a)
printf(", %d", sortedArray[a]);
printf("]");
// wait(NULL);
// close(mypipe2[1]); // Closes writing
// int median;
// read(mypipe1[0], median, sizeof(charian));
exit(0);
}
else {
pid2 = fork();
// Other child
if (pid2 == 0) {
printf("pid == (pid_t) 0\n");
/* This is the child process.
Close other end first. */
close(mypipe0[1]);
char valuesArray[5];
for (int a = 0; a < 5; a++)
read(mypipe0[0], &valuesArray[a], sizeof(char));
printf("finish reading mypipe0");
std::sort(valuesArray, valuesArray + 5);
printf("sorted");
close(mypipe1[0]);
close(mypipe2[0]);
for (int a = 0; a < 5; a++) {
write(mypipe1[1], &valuesArray[a], sizeof(char));
write(mypipe2[1], &valuesArray[a], sizeof(char));
}
close(mypipe1[1]);
close(mypipe2[1]);
exit(0);
}
}
}
I expect the output to be 2 4 5 6 7 from the given command line arguments of 4 2 5 6 7. Instead, I get [1, 28932, 5, 6, -14276913]
The else branch is reached when there is a failure in the first fork call.
Your current code structure is,
pid = fork();
if (pid == 0)
{
runFirstChild();
}
else if (pid > 1)
{
runParent();
}
else // This branch is not taken unless there is a failure
{
pid2 = fork();
if (pid2 == 0)
{
runSecondChild();
}
}
You should instead structure it like so,
pid = fork();
if (pid == 0)
{
runFirstChild();
}
else if (pid > 1)
{
pid2 = fork(); // Fork the second child in the parent process
if (pid2 == 0)
{
runSecondChild();
}
else if (pid2 > 1)
{
runParent();
}
}
Need some help with PTHREADS. I want to keep over 1000 threads opened at any time, something like a thread pool. Here is the code :
/*
gcc -o test2 test2.cpp -static -lpthread -lstdc++
*/
#include <iostream>
#include <cstdlib>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <cstring>
#include <stdexcept>
#include <cstdlib>
int NUM_THREADS = 2000;
int MAX_THREADS = 100;
int THREADSTACK = 65536;
struct thread_struct{
int arg1;
int arg2;
};
pthread_mutex_t mutex_;
static unsigned int thread_count = 0;
string exec(const char* cmd)
{
int DEBUG=0;
char buffer[5000];
string result = "";
FILE* pipe = popen(cmd, "r");
if (!pipe && DEBUG) throw runtime_error("popen() failed!");
try
{
while (!feof(pipe))
{
if (fgets(buffer, 128, pipe) != NULL)
{
result += buffer;
}
}
}
catch(...)
{
pclose(pipe);
throw;
}
pclose(pipe);
return result;
}
void *thread_test(void *arguments)
{
pthread_mutex_lock(&mutex_);
thread_count++;
pthread_mutex_unlock(&mutex_);
// long tid;
// tid = (long)threadid;
struct thread_struct *args = (thread_struct*)arguments;
/*
printf("ARG1=%d\n",args->arg1);
printf("ARG2=%d\n",args->arg2);
*/
int thread_id = (int) args->arg1;
/*
int random_sleep;
random_sleep = rand() % 10 + 1;
printf ("RAND=[%d]\n", random_sleep);
sleep(random_sleep);
*/
int random_sleep;
random_sleep = rand() % 10 + 5;
// printf ("RAND=[%d]\n", random_sleep);
char command[100];
memset(command,0,sizeof(command));
sprintf(command,"sleep %d",random_sleep);
exec(command);
random_sleep = rand() % 100000 + 500000;
usleep(random_sleep);
// simulation of a work between 5 and 10 seconds
// sleep(random_sleep);
// printf("#%d -> sleep=%d total_threads=%u\n",thread_id,random_sleep,thread_count);
pthread_mutex_lock(&mutex_);
thread_count--;
pthread_mutex_unlock(&mutex_);
pthread_exit(NULL);
}
int main()
{
// pthread_t threads[NUM_THREADS];
int rc;
int i;
usleep(10000);
srand ((unsigned)time(NULL));
unsigned int thread_count_now = 0;
pthread_attr_t attrs;
pthread_attr_init(&attrs);
pthread_attr_setstacksize(&attrs, THREADSTACK);
pthread_mutex_init(&mutex_, NULL);
for( i=0; i < NUM_THREADS; i++ )
{
create_thread:
pthread_mutex_lock(&mutex_);
thread_count_now = thread_count;
pthread_mutex_unlock(&mutex_);
// printf("thread_count in for = [%d]\n",thread_count_now);
if(thread_count_now < MAX_THREADS)
{
printf("CREATE thread [%d]\n",i);
struct thread_struct struct1;
struct1.arg1 = i;
struct1.arg2 = 999;
pthread_t temp_thread;
rc = pthread_create(&temp_thread, NULL, &thread_test, (void *)&struct1);
if (rc)
{
printf("Unable to create thread %d\n",rc);
sleep(1);
pthread_detach(temp_thread);
goto create_thread;
}
}
else
{
printf("Thread POOL full %d of %d\n",thread_count_now,MAX_THREADS);
sleep(1);
goto create_thread;
}
}
pthread_attr_destroy(&attrs);
pthread_mutex_destroy(&mutex_);
// pthread_attr_destroy(&attrs);
printf("Proccess completed!\n");
pthread_exit(NULL);
return 1;
}
After spawning 300 threads it begins to give
errors, return code from pthread_create() is 11, and after that keeps executing them one by one.
What im i doing wrong?
According to this website, error code 11 corresponds to EAGAIN which means according to this:
Insufficient resources to create another thread.
A system-imposed limit on the number of threads was encountered.
Hence to solve your problem either create less threads or wait for running ones to finish before creating new ones.
You can also change default thread stack size see pthread_attr_setstacksize
I am writing this code, which basically takes an argument specifying how many child threads I want, forks to get them, and then prints all the pids which are stored in an array.
This would be fine if only the parent would need the PIDs, but I also need the child to get their IDS (pcid). I copy and pasted some code from the net (which I didn't really understand), so I'm not sure why it's not working.
I get a segmentation error after the first PID prints.
What's wrong here?
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <sys/shm.h>
#include <sys/ipc.h>
int main(int argc, char *argv[])
{
if(argc < 2) {
printf("ERROR: No arguments fed.\n");
exit(-1);
}
int amount = atoi(argv[1]);
int i;
int pid = 1;
int pcid = 0;
key_t key;
int shmid;
int *arr[amount];
key = ftok("thread1.c",'R');
shmid = shmget(key, 1024, 0644 | IPC_CREAT);
for(i = 0; i < amount; i++)
{
if(pid != 0)
{
pid = fork();
}
*arr = shmat(shmid, (void *) 0, 0);
if(pid != 0)
{
*arr[i] = pid;
}
else
{
pcid = *arr[i];
break;
}
}
if(pid != 0)
{
printf("Printing PID Array:\n");
for(i =0; i < amount; i++)
{
printf("%d\n", *arr[i]);
}
}
else
{
printf("My PID: %d\n",pcid);
}
}
you are using an array of pointers. And in line *arr = shmat(shmid, (void *) 0, 0) you assigned the shared memory access point to the first element of array. Now when you are using *arr[i] = pid it will go to the array i+1 element where an unknown address stays and you try to put a value there. so you got segmentation fault.
When trying run this code: At first it prints "Process some_id BEFORE enter" for each semaphor (2 times). Then it hangs. What is incorrect?
# include <sys/ipc.h>
# include <sys/sem.h>
# include <unistd.h>
# include <errno.h>
# include <stdio.h>
# include <stdlib.h>
# include <iostream>
int seminit()
{
key_t key = ftok("/bin", 1);
int semid = semget (key, 1, IPC_CREAT | IPC_EXCL | 600);
if(-1 == semid)
if(EEXIST == errno)
semid = semget(key, 1, 0);
return semid;
}
void uninit(int semid)
{
semctl(semid, 0, IPC_RMID);
}
void semlock(int semid)
{
struct sembuf p_buf;
p_buf.sem_num = 0;
p_buf.sem_op = -1;
p_buf.sem_flg = SEM_UNDO;
if(semop(semid, &p_buf, 1) == -1)
printf("semlock failed: ERRNO: %d\n", errno);
}
void semunlock(int semid)
{
struct sembuf v_buf;
v_buf.sem_num = 0;
v_buf.sem_op = 1;
v_buf.sem_flg = SEM_UNDO;
if(semop(semid, &v_buf, 1) == -1)
printf("semunlock failed: ERRNO: %d\n", errno);
}
void some_function()
{
int semid = seminit();
pid_t pid = getpid();
printf("Process %d BEFORE enter\n", pid);
semlock(semid);
printf("Process %d IN Critical section\n", pid);
sleep(10);
semunlock(semid);
printf("Process %d AFTER leave\n", pid);
uninit(semid);
}
int main(int argc, char** argv)
{
for(int i = 0; i < 2; ++i)
if(0 == fork())
some_function();
return (EXIT_SUCCESS);
}
Seems that only a child is generated (I think that is not intended), still, I believe there is a missing wait before the return of the main process, which means that the main process will end faster than the child process and let it "hanged" (this can be part of the issue but is not maybe the hole issue, check that for cycle before).