Why semop() hangs? - c++

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).

Related

libusb_blk_transfer works but libusb_fill_bulk_transfer/libusb_submit_transfer does not

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.

Linux - Shell does not redirect outputs

I created a simple shell in Linux using fork() and execvp(). It works fine with cat, ls etc. but when I try to redirect its output like ./hello.o > output.txt it doesn't work.
I am guessing I didn't provide the write path to look for the definitions. My shell is currently searching on /bin/ path where most of the commands are stored.
Here is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define ARG_SIZE 100 // MAX LENGTH FOR ARGUMENTS
#define PATH "/bin/" // PATH FOR ARGUMENTS
int main() {
char inputLine[BUFSIZ];
char *argv[ARG_SIZE];
// for path + argv
char programPath[200];
while (1) {
printf("myshell> ");
// check if ctrl + D is pressed
if (fgets(inputLine, BUFSIZ, stdin) == NULL)
break;
inputLine[strlen(inputLine) - 1] = '\0';
// check if exit is typed
if (strcmp(inputLine, "exit") == 0)
break;
int i = 0;
argv[0] = strtok(inputLine, " \n");
for (i = 0; argv[i] && i < ARG_SIZE-1; ++i)
argv[++i] = strtok(NULL, " \n");
// create a fork call
pid_t pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
// parent
if (pid != 0) {
wait();
// child
} else {
strcat(programPath, argv[0]);
// will not return unless it fails
execvp(programPath, argv);
perror("execvp");
exit(1);
}
}
return 0;
}

How to get the number of remaining threads after terminating a thread in windows thread? c++

After terminating each thread using the below program, I need to print the remaining threads with ids every time, for which I am using GetExitCodeThread function but it is returning some garbage value.What could I be doing wrong?Also, how to print the remaining threads after getting the exitCode correct?
#define NUM_THREADS 10
#include <windows.h>
#include <stdio.h>
#include <process.h>
typedef struct
{
int Id;
HANDLE hTerminate;
} ThreadArgs;
unsigned _stdcall ThreadFunc( void *pArgs )
{
LPDWORD exitCode;
HANDLE hTerminate = ((ThreadArgs *)pArgs)->hTerminate;
int id = ((ThreadArgs *)pArgs)->Id;
// run until we are told to terminate while (1)
while(1)
{
// Check to see if we should terminate
if (WaitForSingleObject(hTerminate, 0) == WAIT_OBJECT_0)
{
// Terminate Thread - we call ResetEvent to
// return the terminate thread to its non-
// signaled state, then exit the while() loop
printf ("Terminating Thread %d\n", id);
GetExitCodeThread(hTerminate,exitCode);
printf("%d",exitCode);
ResetEvent(hTerminate);
break;
}
// we can do our work now ...
// simulate the case that it takes
// to do the work the thread has to do
Sleep(1000);
}
_endthreadex(0);
return 0;
}
int main(int argc, char* argv[])
{
int i=0;
unsigned int threadID[NUM_THREADS];
HANDLE hThread[NUM_THREADS];
ThreadArgs threadArgs[NUM_THREADS];
// Create 10 threads
printf("Total number of threads= %d\n", NUM_THREADS);
for (i = 0; i < NUM_THREADS;i++)
{
printf("Thread number %d \n",i);
}
for (int i = 0; i<NUM_THREADS;i++)
{
threadArgs[i].Id = i;
threadArgs[i].hTerminate = CreateEvent(NULL,TRUE,FALSE,NULL);
hThread[i] = (HANDLE)_beginthreadex(NULL,0,&ThreadFunc,&threadArgs[i], 0, &threadID[i]);
}
printf("To kill a thread (gracefully), press 0-9, "" then <Enter>. \n");
printf("Press any other key to exit.\n");
while (1)
{
int c = getc(stdin);
if (c == '\n')
continue;
if (c < '0' || c > '9')
break;
SetEvent(threadArgs[c -'0'].hTerminate);
}
return 0;
}
GetExitCodeThread() expects a HANDLE to a thread object, but you are passing it a HANDLE to an event object instead. You are also passing it an uninitialized pointer to write the exit code to. As such, GetExitCodeThread() is goes to fail with an error that you are ignoring, and the exit code will not be assigned any meaningful value.
Not that it matters, because GetExitCodeThread() is useless to call inside a thread that is still running, it will set the exit code to STILL_ACTIVE. You are supposed to call GetExitCodeThread() in a different thread than the one that is being terminated.
Try something more like this instead:
#include <windows.h>
#include <stdio.h>
#include <process.h>
#define MAX_THREADS 10
typedef struct
{
int Id;
DWORD dwThreadId;
HANDLE hThread;
HANDLE hTerminate;
} ThreadArgs;
unsigned __stdcall ThreadFunc( void *arg )
{
ThreadArgs *pArgs = (ThreadArgs *) arg;
// run until we are told to terminate while (1)
while(1)
{
// Check to see if we should terminate
if (WaitForSingleObject(pArgs->hTerminate, 0) == WAIT_OBJECT_0)
{
// Terminate Thread - exit the while() loop
printf ("Thread %d terminate signal detected\n", pArgs->Id);
break;
}
// we can do our work now ...
// simulate the case that it takes
// to do the work the thread has to do
Sleep(1000);
}
return 0;
}
int main(int argc, char* argv[])
{
int i;
ThreadArgs threadArgs[MAX_THREADS];
int numThreadsRunning = 0;
memset(&ThreadArgs, 0, sizeof(ThreadArgs));
// Create 10 threads
printf("Creating %d threads\n", MAX_THREADS);
for (i = 0; i < MAX_THREADS; ++i)
{
printf("Thread number %d: ", i);
threadArgs[i].Id = i;
threadArgs[i].hTerminate = CreateEvent(NULL, TRUE, FALSE, NULL);
threadArgs[i].hThread = (HANDLE) _beginthreadex(NULL, 0, &ThreadFunc, &threadArgs[i], 0, &threadArgs[i].dwThreadId);
if (threadArgs[i].hThread != NULL)
{
printf("Created\n");
++numThreadsRunning;
}
else
printf("Not Created!\n");
}
printf("Threads running: %d\n", numThreadsRunning);
printf("To kill a thread (gracefully), press 0-%d, then <Enter>.\n", MAX_THREADS-1);
printf("Press any other key to exit.\n");
while (1)
{
int c = getc(stdin);
if (c == '\n')
continue;
if ((c < '0') || (c > '9'))
break;
int id = c - '0';
if (threadArgs[id].hThread != NULL)
{
printf ("Signaling Thread %d to Terminate\n", id);
SetEvent(threadArgs[id].hTerminate);
WaitForSingleObject(threadArgs[id].hThread, INFINITE);
DWORD exitCode = 0;
GetExitCodeThread(threadArgs[id].hThread, &exitCode);
CloseHandle(threadArgs[id].hThread);
threadArgs[id].hThread = NULL;
printf ("Thread %d Terminated. Exit Code: %u\n", id, exitCode);
--numThreadsRunning;
printf ("Threads still running: %d\n", numThreadsRunning);
}
else
printf ("Thread %d is not running\n", id);
}
if (numThreadsRunning > 0)
{
printf ("Signaling remaining Threads to Terminate\n");
HANDLE hThreads[MAX_THREADS];
DWORD numThreads = 0;
for (i = 0; i < MAX_THREADS; ++i)
{
if (threadArgs[i].hThread != NULL)
{
hThreads[numThreads] = threadArgs[i].hThread;
++numThreads;
SetEvent(threadArgs[i].hTerminate);
}
}
WaitForMultipleObjects(numThreads, hThreads, TRUE, INFINITE);
for (i = 0; i < MAX_THREADS; ++i)
{
if (hThreads[i].hThread)
CloseHandle(hThreads[i].hThread);
if (hThreads[i].hTerminate)
CloseHandle(hThreads[i].hTerminate);
}
printf ("Threads Terminated\n");
}
return 0;
}
Have a look at this msdn article:
Traversing the Thread List
https://msdn.microsoft.com/en-us/library/windows/desktop/ms686852(v=vs.85).aspx
There is sample code on how to list the threads for a process.
~snip
#include <windows.h>
#include <tlhelp32.h>
#include <tchar.h>
// Forward declarations:
BOOL ListProcessThreads( DWORD dwOwnerPID );
void printError( TCHAR* msg );
int main( void )
{
ListProcessThreads(GetCurrentProcessId() );
return 0;
}
BOOL ListProcessThreads( DWORD dwOwnerPID )
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;
// Take a snapshot of all running threads
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return( FALSE );
// Fill in the size of the structure before using it.
te32.dwSize = sizeof(THREADENTRY32 );
// Retrieve information about the first thread,
// and exit if unsuccessful
if( !Thread32First( hThreadSnap, &te32 ) )
{
printError( TEXT("Thread32First") ); // Show cause of failure
CloseHandle( hThreadSnap ); // Must clean up the snapshot object!
return( FALSE );
}
// Now walk the thread list of the system,
// and display information about each thread
// associated with the specified process
do
{
if( te32.th32OwnerProcessID == dwOwnerPID )
{
_tprintf( TEXT("\n THREAD ID = 0x%08X"), te32.th32ThreadID );
_tprintf( TEXT("\n base priority = %d"), te32.tpBasePri );
_tprintf( TEXT("\n delta priority = %d"), te32.tpDeltaPri );
}
} while( Thread32Next(hThreadSnap, &te32 ) );
_tprintf( TEXT("\n"));
// Don't forget to clean up the snapshot object.
CloseHandle( hThreadSnap );
return( TRUE );
}
void printError( TCHAR* msg )
{
DWORD eNum;
TCHAR sysMsg[256];
TCHAR* p;
eNum = GetLastError( );
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
sysMsg, 256, NULL );
// Trim the end of the line and terminate it with a null
p = sysMsg;
while( ( *p > 31 ) || ( *p == 9 ) )
++p;
do { *p-- = 0; } while( ( p >= sysMsg ) &&
( ( *p == '.' ) || ( *p < 33 ) ) );
// Display the message
_tprintf( TEXT("\n WARNING: %s failed with error %d (%s)"), msg, eNum, sysMsg );
}

IPC_RMID not work on linux with C++

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.

How to share an array between forks?

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.