In the next code the std::unique_lock lck
is not unlocked in Manager::CommandShell
, despite being explicitly unlocked. I'm able to get "Entering lock" but not "Inside lock", does anybody knows why unlock is not working? Or perhaps it is and it doesen't work as I thought?
std::mutex stdinMutex;
Manager *pman=NULL;
void *StdIn_Reader(void *p)
{
int nbytes;
while(1) /// Infinite loop
{
std::unique_lock<std::mutex> lck{stdinMutex};
nbytes = read(0,pman->stdin_command,MAXCLIENTMSG);
if (nbytes > 0)
{
pman->stdin_command[nbytes]='\0';
/// Signal cmd
pthread_kill(pman->self_id,SIGUSR2);
}
lck.unlock();
}
return NULL;
}
bool Manager::CommandShell(bool started)
{
char command[(MAXCLIENTMSG+1)*MAXNUMCOMMANDS];
// variables to process more than one order in a message (when it happens)
sigset_t newmask;
siginfo_t info;
int rcvd_sig;
// Mask for block all but SIGUSR1 and SIGUSR2 signals
sigemptyset(&newmask);
sigaddset(&newmask, SIGUSR1);
sigaddset(&newmask, SIGUSR2);
pthread_sigmask(SIG_BLOCK, &newmask, NULL);
while (1)
{
do{
rcvd_sig = sigwaitinfo(&newmask, &info);
}while(rcvd_sig==-1);
command[0]='\0';
{
cout << "Entering lock\n";
std::unique_lock<std::mutex> lck{stdinMutex};
cout << "Inside lock\n";
if(strlen(stdin_command)){
strcpy(command+strlen(command),stdin_command);
}
stdin_command[0]='\0';
}
lck.unlock();
}
}
}
In general holding a mutex lock whilst performing a blocking operation like read
will lead to deadlocks.
The easiest solution for your code is likely to read into a temporary buffer then lock the mutex and copy into your data structure:
while(1) /// Infinite loop
{
char temp[MAXCLIENTMSG];
nbytes = read(0,temp,MAXCLIENTMSG);
if (nbytes > 0)
{
std::unique_lock<std::mutex> lck{stdinMutex};
memcpy(pman->stdin_command, temp, nbytes)
pman->stdin_command[nbytes]='\0';
/// Signal cmd
pthread_kill(pman->self_id,SIGUSR2);
}
}