rangermattos rangermattos - 26 days ago 10
C++ Question

Semaphores failing to wait, with reason "Resource temporarily unavailable"

I'm trying to have a parent process wait on multiple child processes signalling, before the parent continues, using an array of unnamed semaphores (one per child process). However, when using sem_wait(), the parent process waits indefinitely, while sem_trywait() returns a "resource temporarily unavailable" error, and continues without the child processes having signalled. Neither sem_init() nor sem_post() return an error.

Relevent portion of the code:

int numsems = concurrent_instrs.size();
std::cout << "Num sems: " << numsems << "\n";
// create semaphores
sem_t* sems = new sem_t[numsems];
for (int i = 0; i < numsems; i++)
{
if (sem_init(&sems[i], 1, 0) < 0)
{
perror("sem initialization failed");
exit(1);
}
}

int child_num = 0;

// perform all calculations in block concurrently
for(unsigned int i = 0; i < concurrent_instrs.size() && !isChild; i++)
{
int pid = fork();
if (pid == -1)
{
perror("Error forking:");
exit(1);
}
if (pid == 0)
{
isChild = true;
instr = concurrent_instrs[i];
}
else
{
child_num++;
}
}
if (isChild)
{
std::cout << "Child process " << child_num << " calculating: " << instr << "\n";
perform_calculation(instr, input_vars, internal_vars, shm_input, shm_internal);
std::cout << "Child process " << child_num << " finished calculating\n";

if (sem_post(&sems[child_num]) < 0)
{
perror("Child signal failed");
}

std::cout << "Child "<< child_num << " signalled\n";

// detach from shared memory
if (shmdt(shm_input) < 0)
{
perror("child shm_input detach failed");
}
if (shmdt(shm_internal) < 0)
{
perror("child shm_internal detach failed");
}
exit(0);
}
else
{
// parent waits for all children to finish
for (int i = 0; i < numsems; i++)
{
std::cout << "Waiting on subprocess " << i << " of " << numsems << "\n";
if (sem_trywait(&sems[i]) < 0)
perror("Parent wait failed");
else
std::cout << "Parent wait " << i << " working\n";
}
std::cout << "Finished waiting\n";

// destroy semaphores
for (int i = 0; i < numsems; i++)
{
if(sem_destroy(&sems[i]) < 0)
{
perror("Sem destroy failed");
exit(2);
}
else
{
std::cout << "Sem " << i << " destroyed\n";
}
}

delete[] sems;
}


Am I setting something up incorrectly, or just misunderstanding how to use semaphores in this situation?

Edit to add: sem_wait() encounters the error regardless of whether the child processes call sem_post() before or after the wait.

Answer

The semaphores allocated with sem_t* sems = new sem_t[numsems]; are not in the shared memory. Therefore each process has its own copy, and posting in the child doesn't affect the parent.

The parent's copy remains locked. sem_trywait fails with EAGAIN, which translates to resource temporarily unavailable explanation.