CGI starting and stopping daemons.

This is a discussion on CGI starting and stopping daemons. within the Apache Web Server forums, part of the Web Server and Related Forums category; I'm writing a CGI app that will provide a user interface to real hardware devices that are part of ...


Go Back   Usenet Forums > Web Server and Related Forums > Apache Web Server

FAQ Members List Calendar Search Today's Posts Mark Forums Read
  #1 (permalink)  
Old 06-06-2004
James Lehman
 
Posts: n/a
Default CGI starting and stopping daemons.

I'm writing a CGI app that will provide a user interface to real hardware
devices that are part of the server, namely one or more SCSI tape drives. I
have a perfectly functional console app that controls the SCSI device the
way I want. It writes its pid to a file when it starts and sets it back to
zero when it terminates. No other instance of this process can be started if
one is already running. The process also writes it current state, every time
it changes, to a status file. The process needs to run as a daemon. It needs
to be started as a background process. It never returns, unless its pid is
sent a kill signal. It will, most likely be started in /etc/rc.d/rc.local.

I want to write a CGI app in C/C++. When the CGI app starts up, it reads the
pid and status files. If the process is not running, it offers a "start"
button. If the process is running, it offers a "stop" button. It calls back
to the same CGI app with an argument to the app of start or stop that calls
commands at the prompt using popen(). Like this:

command = popen("process_name device_name &", "r"); // start
command = popen((string("kill -HUP ") + pid).c_str(), "r"); // stop

I think I need to stick a fork in it somewhere. the CGI shell has to
terminate and that would kill the background process, right?
There are also some issues as to who should own the SCSI device and the pid
and status files.

I did a chmod u+s as root to the console app that the CGI app calls. When I
call the code above to start the process, it does return. A call to ps axf,
from the console as root, shows that the console tape app is running, but
the pid file still shows zero, the status file says "down" and the program
doesn't work. Obviously, I can't kill a pid of zero.

Any thoughts on this situation would be most appreciated!

Thanks.
Have a great day! James. :o)



  #2 (permalink)  
Old 06-07-2004
Kieran Simkin
 
Posts: n/a
Default Re: CGI starting and stopping daemons.

"James Lehman" <james[remove]@akrobiz.com> wrote in message
news:zzKwc.1299$Jp.59508@ord-read.news.verio.net...
> I'm writing a CGI app that will provide a user interface to real hardware
> devices that are part of the server, namely one or more SCSI tape drives.

I
> have a perfectly functional console app that controls the SCSI device the
> way I want. It writes its pid to a file when it starts and sets it back to
> zero when it terminates. No other instance of this process can be started

if
> one is already running. The process also writes it current state, every

time
> it changes, to a status file. The process needs to run as a daemon. It

needs
> to be started as a background process. It never returns, unless its pid is
> sent a kill signal. It will, most likely be started in /etc/rc.d/rc.local.
>
> I want to write a CGI app in C/C++. When the CGI app starts up, it reads

the

C/C++ is not a language, choose one or the other and stick to it.

> pid and status files. If the process is not running, it offers a "start"
> button. If the process is running, it offers a "stop" button. It calls

back
> to the same CGI app with an argument to the app of start or stop that

calls
> commands at the prompt using popen(). Like this:
>
> command = popen("process_name device_name &", "r"); // start
> command = popen((string("kill -HUP ") + pid).c_str(), "r"); // stop
>


You probably don't want to use popen and you almost certainly do not want to
use the & operator to "backgroundify" what you're running.

> I think I need to stick a fork in it somewhere. the CGI shell has to
> terminate and that would kill the background process, right?


Yes, you do, maybe even two. If you fork one process from the CGI script,
the parent will be required to wait() on its child, otherwise you will get
zombies and that's a bad thing. You can either ignore SIGCHILD (man 3
signal) or fork two children. You then almost certainly want to be using one
of the exec() family of functions. Try something like this:

int forkpid;
forkpid = fork();
if (forkpid ==0) {
/* we're the child */
if (fork() == 0) {
/* we're the child of the child */
execl("program")
}
exit(0);
} else {
while (wait(NULL) != forkpid) {}
}


> There are also some issues as to who should own the SCSI device and the

pid
> and status files.
>
> I did a chmod u+s as root to the console app that the CGI app calls. When

I
> call the code above to start the process, it does return. A call to ps

axf,
> from the console as root, shows that the console tape app is running, but
> the pid file still shows zero, the status file says "down" and the program
> doesn't work. Obviously, I can't kill a pid of zero.


what does ps aux tell you is the pid of the application that's running?
Sounds like a zombie to me..


>
> Any thoughts on this situation would be most appreciated!


You might try comp.unix.programmer in future as this isn't really an apache
specific question.

>
> Thanks.
> Have a great day! James. :o)
>
>
>



  #3 (permalink)  
Old 06-07-2004
James Lehman
 
Posts: n/a
Default Re: CGI starting and stopping daemons.

> C/C++ is not a language, choose one or the other and stick to it.

I use classes with inheritance and virtual function to define my device, my
tape, my specific tape drive, etc. The application also relies heavily on
file descriptors, ioctl calls and signal trapping with a termination
function. That's what I call C/C++. Parts of it a pure C. Parts of it are
pure C++.

I've also written polymorphic object oriented programming (POOP) in pure C.
http://freshmeat.net/projects/ezfb/?...01%2C111%2C112

I know the difference between C and C++.

> You probably don't want to use popen and you almost certainly do not want

to
> use the & operator to "backgroundify" what you're running.


Why? It works like this from a script like /etc/rc.d/rc.local.

I don't get how forking twice would get me anywhere better than once.

> what does ps aux tell you is the pid of the application that's running?
> Sounds like a zombie to me..


The process has a real number, but since root didn't start it, when I kill
it or killall, I get no message of its termination. It's just gone. Since it
has no effect on the pid or the status file, it can be started many times.
This has a horrible effect on the machine in general.

> You might try comp.unix.programmer in future as this isn't really an

apache
> specific question.


Well it sort-of-is. It has everything to do with what the user apache can do
on a machine that has lots of stuff owned by root AND it has to do
specifically with the hidden shell that runs the CGI app that is inside of
Apache and how it relates to a real shell in a real console.

Smile. Be Happy. Look at some art.
http://www.akrobiz.com/pc/gallery_index.html

Take care. James. :o)




  #4 (permalink)  
Old 06-07-2004
Tim Orbaker
 
Posts: n/a
Default Re: CGI starting and stopping daemons.



James Lehman wrote:
>>C/C++ is not a language, choose one or the other and stick to it.

>
>
> I use classes with inheritance and virtual function to define my device, my
> tape, my specific tape drive, etc. The application also relies heavily on
> file descriptors, ioctl calls and signal trapping with a termination
> function. That's what I call C/C++. Parts of it a pure C. Parts of it are
> pure C++.
>
> I've also written polymorphic object oriented programming (POOP) in pure C.
> http://freshmeat.net/projects/ezfb/?...01%2C111%2C112
>
> I know the difference between C and C++.
>
>
>>You probably don't want to use popen and you almost certainly do not want

>
> to
>
>>use the & operator to "backgroundify" what you're running.

>
>
> Why? It works like this from a script like /etc/rc.d/rc.local.
>
> I don't get how forking twice would get me anywhere better than once.
>
>
>>what does ps aux tell you is the pid of the application that's running?
>>Sounds like a zombie to me..

>
>
> The process has a real number, but since root didn't start it, when I kill
> it or killall, I get no message of its termination. It's just gone. Since it
> has no effect on the pid or the status file, it can be started many times.
> This has a horrible effect on the machine in general.
>
>
>>You might try comp.unix.programmer in future as this isn't really an

>
> apache
>
>>specific question.

>
>
> Well it sort-of-is. It has everything to do with what the user apache can do
> on a machine that has lots of stuff owned by root AND it has to do
> specifically with the hidden shell that runs the CGI app that is inside of
> Apache and how it relates to a real shell in a real console.
>
> Smile. Be Happy. Look at some art.
> http://www.akrobiz.com/pc/gallery_index.html
>
> Take care. James. :o)
>
>
>
>


Apache won't recognize that that a CGI script is done until the CGI
script and all of its subprocesses exit (or at least send an EOF to
stdout). Here is the proper method [adapted from Unix Network
Programming Volume 1 - W. Richard Stevens].


// Block the hangup (HUP) signal. This is sent to all child processes
// when their parent dies. The hangup signal's default action is to
// terminate the proces. If we don't block it, the next statement
// will terminate the parent.

signal( SIGHUP, SIG_IGN );

// Now, we fork and exit the parent. This places the process in the
// background,
if ( fork() != 0 ) exit( 0 );

// At this point, we are in the background, but still attached to the
// current login session (or CGI execution). We need to make it the
// leader of it's own session. This will prevent it from receiving
// hang up signals when the CGI script dies.
setsid();

// Now, to be sure that we don't later send output that assigns us a
// controlling terminal, we need to close all open file descriptors.
// UNIX doesn't provide a way to either close all open files or to
// determine how many descriptors we are using. We close the first
// sixteen which should be PLENTY in a newly started app (we can
// usually get away with just three, but we err on the side of safety
// here). If you have a log file open a this point, it may well be
// closed. Open your log file AFTER this segment of code.
for ( int x = 0 ; x < 16 ; x++ ) close( x );

// Now, to go from the background process to a full daemon, we need to
// fork yet again. This will make the process detached from any
// session as it's session leader (the process from the first fork)
// will be dead.
signal( SIGHUP, SIG_IGN );
if ( fork() != 0 ) exit( 0 );

// You are now a properly created demon process and may do anything
// else you like at this point. There is no stdout to printf() to.

Hope this helps.

Tim



  #5 (permalink)  
Old 06-07-2004
James Lehman
 
Posts: n/a
Default Re: CGI starting and stopping daemons.

Thanks for the info.
This looks pretty complicated.

Since my goal is to start and stop another process, I think I will rewrite
that process to look at the contents of a control file. If the file says
"go", then go. If the files says "stop" then stop. The process can stay up
the whole time and just act according to the control file.

It will be very easy to write to a file and exit from a CGI script. That
way, there is a complete separation from the CGI app and the daemon. I don't
have to worry about who owns what.

Take care. James. :o)



"Tim Orbaker" <tim@orb.aker.com> wrote in message
news:ZaadnbAbA6Xc61ndRVn-uA@wideopenwest.com...
>
>
> James Lehman wrote:
> >>C/C++ is not a language, choose one or the other and stick to it.

> >
> >
> > I use classes with inheritance and virtual function to define my device,

my
> > tape, my specific tape drive, etc. The application also relies heavily

on
> > file descriptors, ioctl calls and signal trapping with a termination
> > function. That's what I call C/C++. Parts of it a pure C. Parts of it

are
> > pure C++.
> >
> > I've also written polymorphic object oriented programming (POOP) in pure

C.
> > http://freshmeat.net/projects/ezfb/?...01%2C111%2C112
> >
> > I know the difference between C and C++.
> >
> >
> >>You probably don't want to use popen and you almost certainly do not

want
> >
> > to
> >
> >>use the & operator to "backgroundify" what you're running.

> >
> >
> > Why? It works like this from a script like /etc/rc.d/rc.local.
> >
> > I don't get how forking twice would get me anywhere better than once.
> >
> >
> >>what does ps aux tell you is the pid of the application that's running?
> >>Sounds like a zombie to me..

> >
> >
> > The process has a real number, but since root didn't start it, when I

kill
> > it or killall, I get no message of its termination. It's just gone.

Since it
> > has no effect on the pid or the status file, it can be started many

times.
> > This has a horrible effect on the machine in general.
> >
> >
> >>You might try comp.unix.programmer in future as this isn't really an

> >
> > apache
> >
> >>specific question.

> >
> >
> > Well it sort-of-is. It has everything to do with what the user apache

can do
> > on a machine that has lots of stuff owned by root AND it has to do
> > specifically with the hidden shell that runs the CGI app that is inside

of
> > Apache and how it relates to a real shell in a real console.
> >
> > Smile. Be Happy. Look at some art.
> > http://www.akrobiz.com/pc/gallery_index.html
> >
> > Take care. James. :o)
> >
> >
> >
> >

>
> Apache won't recognize that that a CGI script is done until the CGI
> script and all of its subprocesses exit (or at least send an EOF to
> stdout). Here is the proper method [adapted from Unix Network
> Programming Volume 1 - W. Richard Stevens].
>
>
> // Block the hangup (HUP) signal. This is sent to all child processes
> // when their parent dies. The hangup signal's default action is to
> // terminate the proces. If we don't block it, the next statement
> // will terminate the parent.
>
> signal( SIGHUP, SIG_IGN );
>
> // Now, we fork and exit the parent. This places the process in the
> // background,
> if ( fork() != 0 ) exit( 0 );
>
> // At this point, we are in the background, but still attached to the
> // current login session (or CGI execution). We need to make it the
> // leader of it's own session. This will prevent it from receiving
> // hang up signals when the CGI script dies.
> setsid();
>
> // Now, to be sure that we don't later send output that assigns us a
> // controlling terminal, we need to close all open file descriptors.
> // UNIX doesn't provide a way to either close all open files or to
> // determine how many descriptors we are using. We close the first
> // sixteen which should be PLENTY in a newly started app (we can
> // usually get away with just three, but we err on the side of safety
> // here). If you have a log file open a this point, it may well be
> // closed. Open your log file AFTER this segment of code.
> for ( int x = 0 ; x < 16 ; x++ ) close( x );
>
> // Now, to go from the background process to a full daemon, we need to
> // fork yet again. This will make the process detached from any
> // session as it's session leader (the process from the first fork)
> // will be dead.
> signal( SIGHUP, SIG_IGN );
> if ( fork() != 0 ) exit( 0 );
>
> // You are now a properly created demon process and may do anything
> // else you like at this point. There is no stdout to printf() to.
>
> Hope this helps.
>
> Tim
>
>
>



 
Thread Tools Search this Thread
Search this Thread:

Advanced Search
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On



All times are GMT +1. The time now is 05:01 PM.


Powered by vBulletin® Version 3.7.3
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Content Relevant URLs by vBSEO 3.0.0