Prev: Details about how process scheduler works?
Next: clients, was Re: Details about how process scheduler works?
From: john on 13 Apr 2010 02:49 Hi, I have two processes running - one process created a semaphore whilst the other just needs to look at it and perform an operation based on it being set. Here is a rough copy of the code: Process 1: semget(key, 1, IPC_CREAT|IPC_EXCL|S_IRUSR|S_IWUSR|S_IROTH|S_IWOTH) semctl(m_nSemID, 0, SETALL, arg) struct sembuf stSemBuf[1]; stSemBuf[0].sem_num = 0; stSemBuf[0].sem_op = 1; while(bLoop) { if(semop(m_nSemID, stSemBuf, 1)!=0) { .....error } } Process 2: struct sembuf stSemBuf[1]; stSemBuf[0].sem_num = 0; stSemBuf[0].sem_op = -1; while(bLoop) { if(semop(nSemKey, stSemBuf, 1)==0) { ...do something } } Everything seems to run fine for about 5 minutes then I get errors in process 1 semop with ERANGE. I had a read of the man pages but can't figure out why I would get this error as I am not setting the SEM_UNDO flag. Can anyway provide any insight into my problem or point me in the right direction to sorting it out myself? Cheers, John.
From: Ersek, Laszlo on 13 Apr 2010 12:07 On Tue, 13 Apr 2010, john wrote: > I have two processes running - one process created a semaphore whilst > the other just needs to look at it and perform an operation based on it > being set. Here is a rough copy of the code: > > [...] > > Everything seems to run fine for about 5 minutes then I get errors in > process 1 semop with ERANGE. I had a read of the man pages but can't > figure out why I would get this error as I am not setting the SEM_UNDO > flag. Am I right to say that you race one process against another, the first incrementing the semaphore value in a tight loop, the second decrementing it? If so, and the first (the incrementing one) is for whatever reason faster, then the semaphore value keeps increasing in the long term, and then http://www.opengroup.org/onlinepubs/9699919799/functions/semop.html [ERANGE] An operation would cause a semval to overflow the system-imposed limit, or an operation would cause a semadj value to overflow the system-imposed limit. The most recent Linux manual page on semop() <http://www.kernel.org/doc/man-pages/online/pages/man2/semop.2.html> says, ERANGE For some operation sem_op+semval is greater than SEMVMX, the implementation dependent maximum value for semval. Even if there is no "strict" system-imposed limit, <http://www.opengroup.org/onlinepubs/9699919799/basedefs/sys_sem.h.html> says: ----v---- A semaphore shall be represented by an anonymous structure, which shall include the following members: unsigned short semval Semaphore value. ----^---- Thus USHRT_MAX is a natural limit. lacos
From: john on 14 Apr 2010 10:04 Ersek, Laszlo wrote: > On Tue, 13 Apr 2010, john wrote: > >> I have two processes running - one process created a semaphore whilst >> the other just needs to look at it and perform an operation based on >> it being set. Here is a rough copy of the code: >> >> [...] >> >> Everything seems to run fine for about 5 minutes then I get errors in >> process 1 semop with ERANGE. I had a read of the man pages but can't >> figure out why I would get this error as I am not setting the SEM_UNDO >> flag. > > Am I right to say that you race one process against another, the first > incrementing the semaphore value in a tight loop, the second > decrementing it? If so, and the first (the incrementing one) is for > whatever reason faster, then the semaphore value keeps increasing in the > long term, and then > I guess there is a race condition yes. I put a counter in and the first process hits about ~47000 and the second process hits ~14000 when the error occurs. I think my understanding of semaphores must be wrong - I didn't realize that I had a incrementing semaphore. I was meaning to create a binary semaphore i.e. only use it to keep the second process informed that something has happened. I don't want to consume every single semaphore that is set and that is why I thought a binary semaphore would be ok. Can you suggest a solution to my problem where I need one process to tell another that something has happened e.g. event? Regards, John.
From: David Schwartz on 14 Apr 2010 10:57 On Apr 14, 7:04 am, john <j...(a)replyatnewsgroup.com> wrote: > Can you suggest a solution to my problem where I need one process to > tell another that something has happened e.g. event? Can you be more precise? Do you only have one event? Or do you want the second process to be able to wait until the status of something has changed? The obvious answer is to use a process-shared mutex and a process- shared condition variable with a predicate variable in shared memory as well. DS
From: Ersek, Laszlo on 14 Apr 2010 11:25 On Wed, 14 Apr 2010, john wrote: > Ersek, Laszlo wrote: >> >> Am I right to say that you race one process against another, the first >> incrementing the semaphore value in a tight loop, the second >> decrementing it? If so, and the first (the incrementing one) is for >> whatever reason faster, then the semaphore value keeps increasing in >> the long term, and then >> > > I guess there is a race condition yes. I put a counter in and the first > process hits about ~47000 and the second process hits ~14000 when the > error occurs. The system-imposed limit on the value of the conceptual semval member seems to be 32767, then. (32767 ~= 47000 - 14000.) > I think my understanding of semaphores must be wrong - I didn't realize > that I had a incrementing semaphore. I was meaning to create a binary > semaphore i.e. only use it to keep the second process informed that > something has happened. I don't want to consume every single semaphore > that is set and that is why I thought a binary semaphore would be ok. After posting my followup, I also changed my mind a bit: your processes probably didn't spin in tight loops, they rather were a heavy-weight producer and a heavy-weight consumer, and the producer worked faster. I thought the semaphore was okay for representing the current length of the work queue, but then it was a strongly bounded one, at the very most holding USHRT_MAX jobs. I considered suggesting another semaphore for representing the empty slots in the queue, so that you can block on a full queue in the producer, not only on an empty queue in the consumer. > Can you suggest a solution to my problem where I need one process to > tell another that something has happened e.g. event? Which SUS version are you coding for? Starting with v2, you could use process-shared POSIX threads mutexes and condition variables. If you're coding for SUSv1, you could send non-queued signals (I'm too lazy to check now if SUSv1 supports queued signals at all), eg. SIGUSR1. I assume your consumer is already written to process all outstanding events when a single notification (of some kind) is delivered, because you seem to have supposed from the start that pending notifications coalesce. Functions to use in the producer: kill(). Functions to use in the consumer: sigemptyset(), sigaddset(), sigprocmask(), sigaction(), sigsuspend(). I'll assume the consumer is single-threaded, you don't fiddle with signal actions and masks otherwise, and whenever you wait for the notification, you wait for nothing else. #define _XOPEN_SOURCE /* SUSv1 */ #include <assert.h> /* assert() */ #include <signal.h> /* sigaction() etc */ #include <errno.h> /* errno */ static sigset_t usr1_unblk; static void usr1_handle(int sig) { assert(SIGUSR1 == sig); } static void usr1_setup(void) { int ret; struct sigaction sa; /* reuse sa_mask for sigprocmask(); it won't hurt sigaction() either */ ret = sigemptyset(&sa.sa_mask); assert(0 == ret); ret = sigaddset(&sa.sa_mask, SIGUSR1); assert(0 == ret); ret = sigprocmask(SIG_BLOCK, &sa.sa_mask, &usr1_unblk); assert(0 == ret); sa.sa_handler = &usr1_handle; sa.sa_flags = 0; ret = sigaction(SIGUSR1, &sa, 0); assert(0 == ret); } static void usr1_wait(void) { int ret; ret = sigsuspend(&usr1_unblk); assert(-1 == ret && EINTR == errno); } Cheers, lacos
|
Next
|
Last
Pages: 1 2 Prev: Details about how process scheduler works? Next: clients, was Re: Details about how process scheduler works? |