[comp.unix.questions] signals to running processes

cjosta@taux01.UUCP (Jonathan Sweedler) (11/30/88)

I have a program that takes a long time to finish running.  From time
to time (sometimes never, sometimes more frequently) I would like to
find out the current status.  The way I accomplish this is to send one
of the user defined signals (SIGUSR1 - no. 30) to the process.  The
process has a signal handler that catches this signal and writes out
the current state (number of loops done, how long it has been running,
when it will finish, etc.).  This all works fine but only I (the owner
of the process) can send the signal.  If my boss, for example, wants to
look at the status of the process, he can't.

My questions are these:  
1) Is there any way for someone who is not the owner of a process to
send the process a signal?

2) Or, is there another way for a random user to cause a program to
asynchronously print out a status report (or perform some action) once
it has started running?

I know I can have the program print out a status report every 
x minutes/hours/loops/whatever, but I don't want this.  I want the
report to be printed out only when specified to do so.

I could also probably (haven't done this yet) write a shell script that
would send the signal and is setuid to me but then if different people
run the program (other than me), there must be different shell scripts 
that are setuid to each person who might run the program.  For example,
if either user A or user B might run the program, but it is user C that
wants the progress report, then there must be a shell script setuid'ed 
to A and one setuid'ed to B.  Is there a cleaner approach?

-- 
Jonathan Sweedler  ===  National Semiconductor Israel
UUCP:    ...!{amdahl,hplabs,decwrl}!nsc!taux01!cjosta
Domain:  cjosta@taux01.nsc.com

hudson@vsedev.VSE.COM (C Hudson Hendren III) (12/01/88)

In article <950@taux01.UUCP> cjosta@taux01.UUCP (Jonathan Sweedler) writes:
>I have a program that takes a long time to finish running.  From time
>to time (sometimes never, sometimes more frequently) I would like to
>find out the current status.  The way I accomplish this is to send one
>of the user defined signals (SIGUSR1 - no. 30) to the process.  The
>process has a signal handler that catches this signal and writes out
>the current state (number of loops done, how long it has been running,
>when it will finish, etc.).  This all works fine but only I (the owner
>of the process) can send the signal.  If my boss, for example, wants to
>look at the status of the process, he can't.
>
>I know I can have the program print out a status report every 
>x minutes/hours/loops/whatever, but I don't want this.  I want the
>report to be printed out only when specified to do so.
>
>Is there a cleaner approach?

If you are running under System 5, you can use the interprocess
communication facility.  Have the program set up a message queue when it
starts.  In order to talk to the program, you write another program which
opens the message queue and sends a message containing the tty number.  You
make this inquire program setuid to the uid of the running program since it
will want to send a SIGUSR1 signal to the program.  The running program
catches the signal and looks to see what is waiting in the message queue.
Upon finding the tty number of the requestor, it writes a message upon that
console.  As an alternative, you can have the running program send its
status back through the message queue (thismakes it easier if you are in the
habit of having unwritable ttys).

You will certainly want to RTFM for more information on how to do this.
Once you get in the habit of using the SVID IPC facility, you will find
numerous uses such as this.
-- 
==> ..!uunet!vsedev!hudson  [hudson@vsedev.vse.com]  (C Hudson Hendren III) <==
==> These are my opinions and are not necessarily those of VSE Corporation. <==
==>	   MS-DOS was created to keep idiots away from UNIX computers	    <==

logan@vsedev.VSE.COM (James Logan III) (12/01/88)

In article <950@taux01.UUCP> cjosta@taux01.UUCP (Jonathan Sweedler) writes:
# I have a program that takes a long time to finish running.  From time
# to time (sometimes never, sometimes more frequently) I would like to
# find out the current status.  The way I accomplish this is to send one
# of the user defined signals (SIGUSR1 - no. 30) to the process.  The
                                             ^^
SIGUSR1 is 16 under System V, so you either made a typo or you're
using a BSD system.  MY RESPONSE WILL NOT HELP YOU IF YOU USE
BSD UNIX, but it may give people in this newsgroup some good ideas.  

# 1) Is there any way for someone who is not the owner of a process to
# send the process a signal?

Not without being root or you.  Writing a setuid program would work, but
is rather clumsy.

# 2) Or, is there another way for a random user to cause a program to
# asynchronously print out a status report (or perform some action) once
# it has started running?

Yes, use shared memory.  Just use shmget(2) to get a hunk of
memory as large as an integer, use shmat(2) to get a pointer to
the integer, set the integer value to 0, and test the value
somewhere that's convenient in your code.  When the value is 1,
print out a report, then set the integer value back to 0.   

Then write a simple program that you and your boss can run that
uses the same key for shmget(2), use shmat(2) to get a pointer to
the same integer, and set the integer value to 1.   

			-Jim

-- 
Jim Logan		logan@vsedev.vse.com
(703) 892-0002		uucp:	..!uunet!vsedev!logan
			inet:	logan%vsedev.vse.com@uunet.uu.net

guy@auspex.UUCP (Guy Harris) (12/01/88)

>SIGUSR1 is 16 under System V, so you either made a typo or you're
>using a BSD system.  MY RESPONSE WILL NOT HELP YOU IF YOU USE
>BSD UNIX,

Not so fast:

	bootme% egrep SIGUSR1 /usr/include/sys/signal.h
	#define SIGUSR1 30      /* user defined signal 1 */
	bootme% egrep shmat /usr/lib/lint/llib-lc
	char *  shmat(i, a, f) char *a; { return (a); }

There are several systems that come to mind that 1) have SIGUSR1 as 30
(by virtue of having picked up the 4.3BSD signal set) and 2) have
"shmat" (by virtue of having picked up System V IPC).  SunOS releases
3.2 and later have both; I think Ultrix has "shmat" and probably has
SIGUSR1 as 30 as well.

maart@cs.vu.nl (Maarten Litmaath) (12/02/88)

cjosta@taux01.UUCP (Jonathan Sweedler) writes:

\...  This all works fine but only I (the owner
\of the process) can send the signal.  If my boss, for example, wants to
\look at the status of the process, he can't.

\My questions are these:  
\1) Is there any way for someone who is not the owner of a process to
\send the process a signal?

If your boss is root, he can :-)

\2) Or, is there another way for a random user to cause a program to
\asynchronously print out a status report (or perform some action) once
\it has started running?

You could let a child of the program test if a certain file in /tmp
exists, and, if so, signal the parent; anyone can make the file, and it's
still a process of yours (the child) who's doing the signaling. The
signal handler could look at the owner of the file, to determine who to
send the status report to. By using a child process the asynchronous
signal scheme is still possible; you'd rather not let the parent constantly
check /tmp for the file.

\...
\I could also probably (haven't done this yet) write a shell script that
                                                       ^^^^^^^^^^^^
\would send the signal and is setuid to me but then if different people
                              ^^^^^^

Aaaaaaaaaaaaarrrrrrrrrrrrgh!!!!!
Haven't you followed the `setuid shell scripts' discussion?
-- 
fcntl(fd, F_SETFL, FNDELAY):          |Maarten Litmaath @ VU Amsterdam:
      let's go weepin' in the corner! |maart@cs.vu.nl, mcvax!botter!maart

logan@vsedev.VSE.COM (James Logan III) (12/02/88)

In article <555@auspex.UUCP> guy@auspex.UUCP (Guy Harris) writes:
# >SIGUSR1 is 16 under System V, so you either made a typo or you're
# >using a BSD system.  MY RESPONSE WILL NOT HELP YOU IF YOU USE
# >BSD UNIX,
# 
# Not so fast:
# 
# There are several systems that come to mind that 1) have SIGUSR1 as 30
# (by virtue of having picked up the 4.3BSD signal set) and 2) have
# "shmat" (by virtue of having picked up System V IPC).  SunOS releases
# 3.2 and later have both; I think Ultrix has "shmat" and probably has
# SIGUSR1 as 30 as well.

That may very well be, but I was simply trying to state that
if he does not have System V, chances are he won't have *shared
memory*.  If he is running Ultrix and has shared memory, then my
suggestion will work for him and he will be a happy person.  

By the way, I thought of this after reading Hudson Hendron's
posting:  

In addition to the integer stored in the shared memory segment I
posted about, a character array can be used to pass a filename
(such as "/tmp/dumpfile" or "/dev/tty11") so that the program
will open that file and dump the report.  This way the report can
be sent somewhere besides the system printer via "lp" each time
a dump is requested.

If it is possible that more than one person at a time will be
requesting a report, you should use semaphores to lock the shared
memory resource.  The System V semaphores make the implementation
of the Dekker P/V algorithm very easy.  (I have a generalized
locking mechanism already written if you want it.)

Testing one integer in a loop in the program will be MUCH faster
than pushing 5 arguments on the stack and calling msgrcv() in
order to periodically poll a message queue like Hudson suggested.  

			-Jim

-- 
Jim Logan		logan@vsedev.vse.com
(703) 892-0002		uucp:	..!uunet!vsedev!logan
			inet:	logan%vsedev.vse.com@uunet.uu.net

les@chinet.chi.il.us (Leslie Mikesell) (12/02/88)

In article <950@taux01.UUCP> cjosta@taux01.UUCP (Jonathan Sweedler) writes:

>2) Or, is there another way for a random user to cause a program to
>asynchronously print out a status report (or perform some action) once
>it has started running?

If you are running SysV you can have the program fork off a process
that creates a FIFO with appropriate write permissions and blocks
waiting for someone to write a command to it.  When it reads a command
it would send a signal to its parent.  You might also set up a
pipe from the child to the parent so that the details of the command
could be passed (such as the device or another FIFO name to send the
progress report to).  If response doesn't have to be instant, the main
process could periodically do a non-blocking read on the FIFO instead
of using a child process.  I suppose that something similar is possible
with sockets under BSD.

Les Mikesell

mkhaw@teknowledge-vaxc.ARPA (Mike Khaw) (12/02/88)

<555@auspex.UUCP>, by guy@auspex.UUCP (Guy Harris):
> There are several systems that come to mind that 1) have SIGUSR1 as 30
> (by virtue of having picked up the 4.3BSD signal set) and 2) have
> "shmat" (by virtue of having picked up System V IPC).  SunOS releases
> 3.2 and later have both; I think Ultrix has "shmat" and probably has
> SIGUSR1 as 30 as well.

On Ultrix 2.2:

% fgrep SIGUSR1 /usr/include/signal.h
 *	Moved SIGUSR1 and SIGUSR2 to 30 and 31 to conform with Berkeley *
#define SIGUSR1   30	/* User signal 1 (from SysV) */

% man -k shmat
shmop, shmat, shmdt (2) - shared memory operations
% nm /lib/libc.a | fgrep shmat
shmat.o:
00000000 T _shmat

Mike Khaw
-- 
internet: mkhaw@teknowledge.arpa
uucp:	  {uunet|sun|ucbvax|decwrl|ames|hplabs}!mkhaw%teknowledge.arpa
hardcopy: Teknowledge Inc, 1850 Embarcadero Rd, POB 10119, Palo Alto, CA 94303

hudson@vsedev.VSE.COM (C Hudson Hendren III) (12/02/88)

In article <1265@vsedev.VSE.COM> logan@vsedev.VSE.COM (James Logan III) writes:
>If it is possible that more than one person at a time will be
>requesting a report, you should use semaphores to lock the shared
>memory resource.  The System V semaphores make the implementation
>of the Dekker P/V algorithm very easy.  (I have a generalized
>locking mechanism already written if you want it.)
>
>Testing one integer in a loop in the program will be MUCH faster
>than pushing 5 arguments on the stack and calling msgrcv() in
>order to periodically poll a message queue like Hudson suggested.  

My original suggestion did not require periodically polling a message
queue.  I had suggested sending a message through the message queue then
sending SIGUSR1 to the running process.

It would only need to call msgrcv() in the signal handler for SIGUSR1.
Checking an integer field on every loop iteration is much more overhead than
just setting a trap handler to call msgrcv().  Of course, if there is going
to be a heavy demand on this feature with constant requests for status
dumps, then the trap handler may become less efficient.  I did not get the
impression that the status dump would be requested with great frequency.
That would be like shaking the jello to see if it had set.

Another advantage of this method is that there is no need to use semaphore
locking.
-- 
==> ..!uunet!vsedev!hudson  [hudson@vsedev.vse.com]  (C Hudson Hendren III) <==
==> These are my opinions and are not necessarily those of VSE Corporation. <==
==>	   MS-DOS was created to keep idiots away from UNIX computers	    <==

logan@vsedev.VSE.COM (James Logan III) (12/02/88)

In article <1267@vsedev.VSE.COM> hudson@vsedev.VSE.COM (C Hudson Hendren III) writes:
# 
# It would only need to call msgrcv() in the signal handler for SIGUSR1.
#

Shared memory could also read the char array the same way on
receipt of SIGUSR1 (it could do it *faster* even!), but I don't
see any good way of sending a signal to the daemon.  

How is another user going to find the PID of the daemon?  Does
the user run 'ps -ef | grep "some_name"' and give it to this
other program as an argument?  Do you hack on the "ps" source
to look through the process table for some_name?

Even if the daemon wrote its PID into some file, what do you
think happens when *two* daemons are running?  If the daemon
writes the PID in append mode, how are do you know which PID is
the one you're interested in?  

# Another advantage of this method is that there is no need to use semaphore
# locking.

That code is trivial and is not necessary on the daemon side.

			-Jim

-- 
Jim Logan		logan@vsedev.vse.com
(703) 892-0002		uucp:	..!uunet!vsedev!logan
			inet:	logan%vsedev.vse.com@uunet.uu.net

dhesi@bsu-cs.UUCP (Rahul Dhesi) (12/02/88)

I have lost track of whether the original poster, who wanted to be able
to send a signal to a process not owned by him, wanted to do it under
under BSD or System V.  If it was BSD, a possibility is to open an
Internet domain socket and set up a SIGIO handler.  When somebody--
anybody--tries to write to the socket a SIGIO signal will be seen by
the process.
-- 
Rahul Dhesi         UUCP:  <backbones>!{iuvax,pur-ee}!bsu-cs!dhesi

guy@auspex.UUCP (Guy Harris) (12/02/88)

>That may very well be, but I was simply trying to state that
>if he does not have System V, chances are he won't have *shared
>memory*.

Again, not so fast; if you have "shmat", which is what I was "grep"ping
for and found in the SunOS "lint" libraries, you presumably have
"*shared memory*" - the "shmat" I'm familiar with is, from the SunOS
manual page:

     shmat() maps the shared memory segment associated  with  the
     shared  memory  identifier  specified by shmid into the data
     segment of the calling process.  Upon successful completion,
     the address of the mapped segment is returned.

These days, I would think twice before saying "if he does not have
System V, chances are he won't have *shared memory*", if "System V" is
to be interpreted as "something that began as the stuff from an AT&T
source tape, as you seemed to have interpreted it.

Looking at the value of SIGUSR1, seeing that it's not 16, and concluding
that they're unlikely to have shared memory is a mistake; if they *do*
have a system that started out with the stuff from a Berkeley source
tape, but that had S5 IPC added, and took the claim that they were
unlikely to have S5 shared memory at face value and didn't look for it
on their system, they'd have lost.

The world isn't neatly divided into "BSD" and "System V"; there are
plenty of systems with features from both, many of which may have
started from BSD but picked up stuff like S5 IPC.

(Of course, in SunOS - and, I think, in at least some other systems,
including S5 from AT&T - it's an optional feature, so you have to
configure the S5 IPC stuff into your system.)