From owner-freebsd-ports Sun Dec 9 1:10:13 2001 Delivered-To: freebsd-ports@hub.freebsd.org Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by hub.freebsd.org (Postfix) with ESMTP id 7373437B416 for ; Sun, 9 Dec 2001 01:10:01 -0800 (PST) Received: (from gnats@localhost) by freefall.freebsd.org (8.11.6/8.11.6) id fB99A1r20905; Sun, 9 Dec 2001 01:10:01 -0800 (PST) (envelope-from gnats) Received: from wwweasel.geeksrus.net (wwweasel.geeksrus.net [64.67.200.82]) by hub.freebsd.org (Postfix) with ESMTP id DF6CB37B416 for ; Sun, 9 Dec 2001 01:03:32 -0800 (PST) Received: (from alane@localhost) by wwweasel.geeksrus.net (8.11.6/8.11.6) id fB992u294974; Sun, 9 Dec 2001 04:02:56 -0500 (EST) (envelope-from alane) Message-Id: <200112090902.fB992u294974@wwweasel.geeksrus.net> Date: Sun, 9 Dec 2001 04:02:56 -0500 (EST) From: Alan E Reply-To: Alan E To: FreeBSD-gnats-submit@freebsd.org X-Send-Pr-Version: 3.113 Subject: ports/32639: freeamp: preference AllowMultipleInstances=false does not work Sender: owner-freebsd-ports@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >Number: 32639 >Category: ports >Synopsis: freeamp: preference AllowMultipleInstances=false does not work >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-ports >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Sun Dec 09 01:10:01 PST 2001 >Closed-Date: >Last-Modified: >Originator: Alan E >Release: FreeBSD 4.4-STABLE i386 >Organization: Geeksrus.NET >Environment: System: FreeBSD wwweasel.geeksrus.net 4.4-STABLE FreeBSD 4.4-STABLE #0: Sun Dec 2 19:14:12 EST 2001 root@wwweasel.geeksrus.net:/usr/obj/usr/src/sys/WWWEASEL i386 >Description: Freeamp has a preference to cause it to delegate actions to an already running freeamp and exit. This does not, and *cannot*, work on FreeBSD the way it is designed. I'm going to describe a mismatch between freeamp's design and FreeBSD's process implementation. The first instance of freeamp to start up creates a semaphore. It puts its PID in the semaphore using semctl. Other freeamps check the value in the semaphore to see if they are subordinate to the first and should exit if the user pref AllowMultipleInstances is false. Semctl uses a union semun to hold values. This union is just a bit misleading. It looks like this (/usr/include/sys/sem.h): union semun { int val; /* value for SETVAL */ struct semid_ds *buf; /* buffer for IPC_STAT & IPC_SET */ u_short *array; /* array for GETALL & SETALL */ }; You'd think you could put an int value into a semaphore with the SETVAL operator, wouldn't you? Yes? You'd be wrong. The value a semaphore can hold is really a "u_short", seen in the array for GETALL and SETALL values. (Is this clearly documented anywhere? Well, no, but I don't recall ever seeing it clearly documented anywhere outside of a Stevens book.) FreeBSD uses an int as its PID type. A 32 bit int. It's defined in , which is included by , which is included by , which is included by . Easy to find. C++ does type checking. So, we'll get warned when we try to store a 32-bit PID into a 16-bit semaphore value, right? Umm, no, that brain-damaged union with the "int val" that really only holds a short int kills our hopes of that. So, can this be fixed? No, not short of a design change in freeamp to communicate that PID some other way to other, non-child freeamp processes. >How-To-Repeat: Set the AllowMultipleInstances preference to false. Start up two Freeamp instances. See two Freeamp instances. Note: if the master freeamp has a low process ID (< USHRT_MAX), the feature should work. If this happens, start and kill a few thousand processes and try again. You can also patch freeamp/base/unix/src/bootstrap.cpp to show you what PID it thinks is its master. I can supply that patch on request. To see the semaphore problem in an isolated state, compile and run this program: ---8<-snip---8<-snip---8<-snip---8<-snip---8<-snip---8<-snip---8<--- #include #include #include #include #include #include #include #include const int iSemKey = 0xDEADBEEF; int main(int argc, char **argv) { int rc = 0; int iCmdSem = -1; key_t tSemKey = iSemKey; int iSemVal; union semun unsem; iCmdSem = semget(tSemKey, 1, IPC_CREAT | 0660); unsem.val = 0xDEADBEEF; semctl(iCmdSem, 0, SETVAL, unsem); iSemVal = semctl(iCmdSem, 0, GETVAL, unsem); if (iSemVal == unsem.val) { printf("semctl(SETVAL) and GETVAL agree\n"); } else { rc = 1; printf("OHSHIT! semctl(SETVAL,%08x) but GETVAL=> %08x\n", unsem.val, iSemVal); } return rc; } ---8<-snip---8<-snip---8<-snip---8<-snip---8<-snip---8<-snip---8<--- >Fix: Design a new method for freeamp to use to communicate the PID of the "master" instance to any new new freeamps that are started. For Extra Credit: Try to get the freeamp team, who have never answered email in my experience, to accept a design-changing patch for an OS they don't officially support. For Extra Extra Credit: Try to get the freeamp team to admit to having brain-lock when they assumed that a PID was a short int. For the Nobel Prize: Fix the "union semun" to have a "short int" val, or fix the semaphore implementation to allow "int" values. Fix all the applications and ports that break because of the fix; remember, things will break because of signedness as well as number of bits. Convince at least 2 authors whose apps you broke that *you* aren't brain-damaged for changing a broken legacy structure that so many things depend on. >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-ports" in the body of the message