www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - Daemon app in D

reply Geert <gertje gertje.org> writes:
Is it possible to create a (linux) daemon in D? And if; how?

Thnx
Jun 07 2005
next sibling parent reply Dejan Lekic <leka entropy.tmok.com> writes:
Read samples in DMD distribution - there is one example there I think.

-- 
...........
Dejan Lekic
  http://dejan.lekic.org
  
Jun 07 2005
parent reply Geert <gertje gertje.org> writes:
No, it is a windows server or something..
I need a real daemon that disconnects from the shell.

Dejan Lekic wrote:
 Read samples in DMD distribution - there is one example there I think.
 

Jun 07 2005
next sibling parent reply James Dunne <james.jdunne gmail.com> writes:
In article <d840t0$2881$1 digitaldaemon.com>, Geert says...
No, it is a windows server or something..
I need a real daemon that disconnects from the shell.

Dejan Lekic wrote:
 Read samples in DMD distribution - there is one example there I think.
 


I've done this before, and it needs to be done with linux system calls. There's no real nice D way to do it. I can't dig up an example of mine for you right now, but I'll get one for you later. Regards, James Dunne
Jun 07 2005
parent Geert <gertje gertje.org> writes:
Thanks, that would be great...

James Dunne wrote:
 In article <d840t0$2881$1 digitaldaemon.com>, Geert says...
 
No, it is a windows server or something..
I need a real daemon that disconnects from the shell.

Dejan Lekic wrote:

Read samples in DMD distribution - there is one example there I think.


I've done this before, and it needs to be done with linux system calls. There's no real nice D way to do it. I can't dig up an example of mine for you right now, but I'll get one for you later. Regards, James Dunne

Jun 07 2005
prev sibling parent reply Dejan Lekic <leka entropy.tmok.com> writes:
So you cannot write an simple D application that reads stdin, writes to
stdout, uses inetd and you run it via "myprog [params] &" ?

-- 
...........
Dejan Lekic
  http://dejan.lekic.org
  
Jun 07 2005
parent Geert <gertje gertje.org> writes:
It doesn't really detach the app from the shell.. Try for instance 
typing Ctrl-Z and then fg, it will bring back the app to the foreground.

Dejan Lekic wrote:
 So you cannot write an simple D application that reads stdin, writes to
 stdout, uses inetd and you run it via "myprog [params] &" ?
 

Jun 07 2005
prev sibling parent reply SeeSchloss <ng seeschloss.org> writes:
On Tue, 07 Jun 2005 12:56:22 +0200, Geert wrote:

 Is it possible to create a (linux) daemon in D? And if; how?
 
 Thnx

An extern (C) fork (); somewhere, and then if (fork ()) exit (0); at the place you want your daemon to daemonize should be enough (since the point is that processes of which the parents are dead are adopted by init, and therefore become deamons). That's what my server uses, and that's the standard way to do it afaict. SeeSchloss.
Jun 07 2005
parent reply SeeSchloss <ng seeschloss.org> writes:
On Tue, 07 Jun 2005 18:42:36 +0200, SeeSchloss wrote:

 extern (C) fork ();

or rather "extern (C) int fork ();", sorry
Jun 07 2005
parent reply Geert <gertje gertje.org> writes:
Thanks, but the program will continue to be connected to the shell try 
this for instance:

extern (C) int fork ();
void main()
{
	// fork returns -1 on failure
	// 0 to childprocess, and the pid
	// number of the child process to the parent
	if(fork()) exit(0);

	while(1)
		printf("You will see this output.\n");
}

SeeSchloss wrote:
 On Tue, 07 Jun 2005 18:42:36 +0200, SeeSchloss wrote:
 
 
extern (C) fork ();

or rather "extern (C) int fork ();", sorry

Jun 07 2005
next sibling parent SeeSchloss <ng seeschloss.org> writes:
On Tue, 07 Jun 2005 19:07:47 +0200, Geert wrote:

 Thanks, but the program will continue to be connected to the shell try 
 this for instance:
 
 extern (C) int fork ();
 void main()
 {
 	// fork returns -1 on failure
 	// 0 to childprocess, and the pid
 	// number of the child process to the parent
 	if(fork()) exit(0);
 
 	while(1)
 		printf("You will see this output.\n");
 }

Well yes it's still attached to the shell of its parent process (until the shell is closed, of course), but a daemon doesn't print on stdout anyway, so that shouldn't be a problem...
Jun 07 2005
prev sibling parent reply Dejan Lekic <leka entropy.tmok.com> writes:
Geert try to write to some log-file and most likely it will continue to fill
it with bytes after you close the shell. :)

-- 
...........
Dejan Lekic
  http://dejan.lekic.org
  
Jun 07 2005
parent reply James Dunne <james.jdunne gmail.com> writes:
The correct way to detach from the shell (and I've written a server app that
does this, just don't have the code with me ATM (at work)) is to create a
different session ID and then fork and kill the parent.

You might want to install some signal handlers in your server if you go this
way.  In your signal handler for SIGINT and SIGTERM you'll want to copy/paste
the code from internal/dmain2.d in phobos that terminates D:

: 	_moduleDtor();
:	gc_term();
:    }
:    catch (Object o)
:    {
:	printf("Error: ");
:	o.print();
:	exit(EXIT_FAILURE);
:    }
:
:    version (linux)
:    {
:	free(am);
:	_STD_critical_term();
:	_STD_monitor_staticdtor();
:    }

I recall that it was a true pain to get D to terminate the program correctly
when you have multiple threads running and you're interrupted by a signal.
Horrible stuff.  I wish phobos had a nice "guaranteed cleanup" system, in case
of emergency death of app.

It is possible to do this easily in your own application, but you'd have to
create a Windows-specific and a Linux-specific version of the code that does
this.  Phobos just feels like a great place for this functionality.  If this
becomes the case, I have some code for Linux I'd like to contribute!  However, I
don't know jack squat about the Windows side of things...


P.S. - I promise you I'll get you the code for this when I get home (in 4 hours
or so).

In article <d84lom$2ql7$1 digitaldaemon.com>, Dejan Lekic says...
Geert try to write to some log-file and most likely it will continue to fill
it with bytes after you close the shell. :)

-- 
...........
Dejan Lekic
  http://dejan.lekic.org
  

Regards, James Dunne
Jun 07 2005
parent reply James Dunne <james.jdunne gmail.com> writes:
And, as promised (later than I had hoped for - I apologize), your linux daemon
in D:

:import	std.c.stdlib;
:version (linux) import std.c.linux.linux;
:
:extern (C) {
:	/// These are for control of termination:
:	void _STD_monitor_staticdtor();
:	void _STD_critical_term();
:	void gc_term();
:	void _moduleDtor();
:
:	version (linux) {
:		alias	int pid_t;
:
:		// daemon functions:
:		pid_t fork();
:		int umask(int);
:		int setsid();
:		int close(int fd);
:
:		// Signal trapping in Linux:
:		typedef void (*sighandler_t)(int);
:		sighandler_t signal(int signum, sighandler_t handler);
:
:		void sighandler(int sig) {
:			write_log("signal %d caught...", sig);
:			terminate();
:		}
:	}
:}
;
:void terminate() {
:	// Custom termination code here:
:
:
:	// Phobos termination (since we can't really make main() return):
:	_moduleDtor();
:	gc_term();
:	version (linux) {
:		//free(am);
:		_STD_critical_term();
:		_STD_monitor_staticdtor();
:	}
:
:	exit(0);
:}
:
:int main(char[][] args) {
:	debug {
:	} else {
:		// Daemonize under Linux:
:		version (linux) {
:			// Our process ID and Session ID
:			pid_t pid, sid;
:
:			// Fork off the parent process
:			pid = fork();
:			if (pid < 0) {
:				exit(EXIT_FAILURE);
:			}
:			// If we got a good PID, then we can exit the parent :process.
:			if (pid > 0) {
:				exit(EXIT_SUCCESS);
:			}
:
:			// Change the file mode mask
:			umask(0);
:		}
:	}
:
:	// Open a log file here:
:
:
:	debug {	} else {
:		version (linux) {
:			// Create a new SID for the child process
:			sid = setsid();
:			if (sid < 0) terminate();
:
:			// Close out the standard file descriptors
:			close(0);
:			close(1);
:			close(2);
:		}
:	}
:
:	version (linux) {
:		signal(SIGABRT, &sighandler);
:		signal(SIGTERM, &sighandler);
:		signal(SIGQUIT, &sighandler);
:		signal(SIGINT, &sighandler);
:	}
:
:	try {
:		// Do your main loop here
:	} catch (ex as Exception) {
:		// Catch an exception
:	} finally {
:		// Terminate the server
:		terminate();
:	}
:
:	return 0;
:}

Hope this helps! =)

In article <d84psn$2uga$1 digitaldaemon.com>, James Dunne says...
The correct way to detach from the shell (and I've written a server app that
does this, just don't have the code with me ATM (at work)) is to create a
different session ID and then fork and kill the parent.

You might want to install some signal handlers in your server if you go this
way.  In your signal handler for SIGINT and SIGTERM you'll want to copy/paste
the code from internal/dmain2.d in phobos that terminates D:

: 	_moduleDtor();
:	gc_term();
:    }
:    catch (Object o)
:    {
:	printf("Error: ");
:	o.print();
:	exit(EXIT_FAILURE);
:    }
:
:    version (linux)
:    {
:	free(am);
:	_STD_critical_term();
:	_STD_monitor_staticdtor();
:    }

I recall that it was a true pain to get D to terminate the program correctly
when you have multiple threads running and you're interrupted by a signal.
Horrible stuff.  I wish phobos had a nice "guaranteed cleanup" system, in case
of emergency death of app.

It is possible to do this easily in your own application, but you'd have to
create a Windows-specific and a Linux-specific version of the code that does
this.  Phobos just feels like a great place for this functionality.  If this
becomes the case, I have some code for Linux I'd like to contribute!  However, I
don't know jack squat about the Windows side of things...


P.S. - I promise you I'll get you the code for this when I get home (in 4 hours
or so).

In article <d84lom$2ql7$1 digitaldaemon.com>, Dejan Lekic says...
Geert try to write to some log-file and most likely it will continue to fill
it with bytes after you close the shell. :)

-- 
...........
Dejan Lekic
  http://dejan.lekic.org
  

Regards, James Dunne

Regards, James Dunne
Jun 07 2005
parent Geert <gertje gertje.org> writes:
Thanks it sure helps!

James Dunne wrote:
 And, as promised (later than I had hoped for - I apologize), your linux daemon
 in D:
 
 :import	std.c.stdlib;
 :version (linux) import std.c.linux.linux;
 :
 :extern (C) {
 :	/// These are for control of termination:
 :	void _STD_monitor_staticdtor();
 :	void _STD_critical_term();
 :	void gc_term();
 :	void _moduleDtor();
 :
 :	version (linux) {
 :		alias	int pid_t;
 :
 :		// daemon functions:
 :		pid_t fork();
 :		int umask(int);
 :		int setsid();
 :		int close(int fd);
 :
 :		// Signal trapping in Linux:
 :		typedef void (*sighandler_t)(int);
 :		sighandler_t signal(int signum, sighandler_t handler);
 :
 :		void sighandler(int sig) {
 :			write_log("signal %d caught...", sig);
 :			terminate();
 :		}
 :	}
 :}
 ;
 :void terminate() {
 :	// Custom termination code here:
 :
 :
 :	// Phobos termination (since we can't really make main() return):
 :	_moduleDtor();
 :	gc_term();
 :	version (linux) {
 :		//free(am);
 :		_STD_critical_term();
 :		_STD_monitor_staticdtor();
 :	}
 :
 :	exit(0);
 :}
 :
 :int main(char[][] args) {
 :	debug {
 :	} else {
 :		// Daemonize under Linux:
 :		version (linux) {
 :			// Our process ID and Session ID
 :			pid_t pid, sid;
 :
 :			// Fork off the parent process
 :			pid = fork();
 :			if (pid < 0) {
 :				exit(EXIT_FAILURE);
 :			}
 :			// If we got a good PID, then we can exit the parent :process.
 :			if (pid > 0) {
 :				exit(EXIT_SUCCESS);
 :			}
 :
 :			// Change the file mode mask
 :			umask(0);
 :		}
 :	}
 :
 :	// Open a log file here:
 :
 :
 :	debug {	} else {
 :		version (linux) {
 :			// Create a new SID for the child process
 :			sid = setsid();
 :			if (sid < 0) terminate();
 :
 :			// Close out the standard file descriptors
 :			close(0);
 :			close(1);
 :			close(2);
 :		}
 :	}
 :
 :	version (linux) {
 :		signal(SIGABRT, &sighandler);
 :		signal(SIGTERM, &sighandler);
 :		signal(SIGQUIT, &sighandler);
 :		signal(SIGINT, &sighandler);
 :	}
 :
 :	try {
 :		// Do your main loop here
 :	} catch (ex as Exception) {
 :		// Catch an exception
 :	} finally {
 :		// Terminate the server
 :		terminate();
 :	}
 :
 :	return 0;
 :}
 
 Hope this helps! =)
 
 In article <d84psn$2uga$1 digitaldaemon.com>, James Dunne says...
 
The correct way to detach from the shell (and I've written a server app that
does this, just don't have the code with me ATM (at work)) is to create a
different session ID and then fork and kill the parent.

You might want to install some signal handlers in your server if you go this
way.  In your signal handler for SIGINT and SIGTERM you'll want to copy/paste
the code from internal/dmain2.d in phobos that terminates D:

: 	_moduleDtor();
:	gc_term();
:    }
:    catch (Object o)
:    {
:	printf("Error: ");
:	o.print();
:	exit(EXIT_FAILURE);
:    }
:
:    version (linux)
:    {
:	free(am);
:	_STD_critical_term();
:	_STD_monitor_staticdtor();
:    }

I recall that it was a true pain to get D to terminate the program correctly
when you have multiple threads running and you're interrupted by a signal.
Horrible stuff.  I wish phobos had a nice "guaranteed cleanup" system, in case
of emergency death of app.

It is possible to do this easily in your own application, but you'd have to
create a Windows-specific and a Linux-specific version of the code that does
this.  Phobos just feels like a great place for this functionality.  If this
becomes the case, I have some code for Linux I'd like to contribute!  However, I
don't know jack squat about the Windows side of things...


P.S. - I promise you I'll get you the code for this when I get home (in 4 hours
or so).

In article <d84lom$2ql7$1 digitaldaemon.com>, Dejan Lekic says...

Geert try to write to some log-file and most likely it will continue to fill
it with bytes after you close the shell. :)

-- 
...........
Dejan Lekic
 http://dejan.lekic.org
 

Regards, James Dunne

Regards, James Dunne

Jun 08 2005