Question about interprocess communication. Sockets. Daemons.

  • (2 Pages)
  • +
  • 1
  • 2

15 Replies - 831 Views - Last Post: 04 July 2013 - 06:11 PM Rate Topic: -----

#1 robgeek  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 104
  • Joined: 15-January 13

Question about interprocess communication. Sockets. Daemons.

Posted 01 July 2013 - 12:33 PM

Good afternoon, everybody. I'm trying to make a program that sends a node of a linked list via socket to a server process that is alive in the background just waiting for more nodes to be added. The program below, sometimes run properly. The problem is that when i put the daemon () function, the child process is merging processor with the parent process. Thus, sometimes, there's no time for the child process to create and configure the socket to wait for the parent process to send us. This program has to be this way, I can not create another client process to run on another terminal. And preferably using sockets, only if there is no other way. How can I solve this problem?
#include "scanner.h"
#include "tasks.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char *argv[]) {
	int status;

	pid_t id_son = fork();
	if( id_son < 0 ){
		printf("Error creating process.\n");
	}else if( id_son == 0 ){
		daemon( 1, 1 );
		printf("I am the child process.\n");

		//I wanted her completely executed first before running parent process. Her body is a socket server.
		addNode( );

		_exit( 0 );
	}
	else{
		waitpid( id_son, &status, 0 );
		printf("I am the father process.\n");
		List *node = createNode( argv[1], argv[2], argv[3] );

		//It behaves as a client, then she should run after the son had finished.
		sendNode( node );

		exit(0);
	}

	return 0;
}


Is This A Good Question/Topic? 0
  • +

Replies To: Question about interprocess communication. Sockets. Daemons.

#2 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 1112
  • View blog
  • Posts: 4,619
  • Joined: 09-June 09

Re: Question about interprocess communication. Sockets. Daemons.

Posted 01 July 2013 - 02:35 PM

The easiest solution (well sleep is easier) is to create a pipe between the child and the parent. Have the parent sit at the end of the pipe waiting for a message from the child. Once the parent receives the message, let the parent go about it's execution.


i.e. (didn't compile, nor test, but idea is there)
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <unistd.h> /* for fork and pipe */
#include <sys/types.h>

int main() {
   int child_pid;
   int pfds[2];
   int sig; /* msg is just a signal, doesn't contain useful information */

   if(pipe(pfds) == -1) {
      fprintf(stderr, "Pipe Failed: ", stderr(errno));
      exit(-1);
   }

   if((child_pid = fork()) < 0) {
      fprintf(stderr, "Child Process Could Not Be Created\n");
   }

   else if(child_pid == 0) { /* child process */
      printf("CHILD PROCESS STARTED\n");
      close(pfds[0]); /* child doesn't read from the pipe, it just signals parent */
      
      /* do importent stuff (critical section), simulated with sleep for an example */
      sleep(3); /* 3 seconds */

      /* tell parent were done doing importent stuff */
      write(pfds[1], &sig, sizeof(sig));
   }
   else { /* parent process */
      close(pfds[1]); /* parent doesn't write from the pipe */
      if(read(pfds[0], &sig, sizeof(sig)) == -1) { /* wait for signal */
         fprintf(stderr, "parent: read error\n");
      }
      else { /* signal has been recieved, let parent start doing work */
          /* This part executes after child signals parent */
      }
   }

   return 0;
}



If you wan't to be lazy, you could make a grand assumption and put a sleep call the the parent process that will be sufficent time for the child to finish it's critical seciton.

This post has been edited by jjl: 01 July 2013 - 02:43 PM

Was This Post Helpful? 1
  • +
  • -

#3 robgeek  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 104
  • Joined: 15-January 13

Re: Question about interprocess communication. Sockets. Daemons.

Posted 01 July 2013 - 04:09 PM

I did it using pipe, like your example, and now is working fine.
Thank you!
Was This Post Helpful? 0
  • +
  • -

#4 robgeek  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 104
  • Joined: 15-January 13

Re: Question about interprocess communication. Sockets. Daemons.

Posted 01 July 2013 - 05:21 PM

I celebrated too soon!
jjl, for example. Let's assume that the part critical you say in line 25 is this function.
And let's assume, too, that I put the function daemon(1, 1) in line 22 in place of the function printf().
Everything is working correctly in the function below, but she doesn't run in background! She stops in accept() funtion and does not release the command terminal to me.
void tasksScheduler( void ) {
	int descServer1, descServer2;
	struct sockaddr_un server, client;
	if( ( descServer1 = socket( AF_UNIX, SOCK_STREAM, 0 ) ) == -1 ) {
		printf("Child process - Error: socket().\n");
		return;
	}

	memset( &server, 0, sizeof( struct sockaddr_un ) );
	server.sun_family = AF_UNIX;
	strcpy( server.sun_path, SOCK_PATH );
	unlink( server.sun_path );

	if( bind( descServer1, ( struct sockaddr * )&server, sizeof( struct sockaddr_un ) ) == -1 ) {
		printf("Child process - Error: bind()\n");
		return;
	}

	if( listen( descServer1, 5 ) == -1 ) {
		printf("Child process - Error: listen( )\n");
		return;
	}

	printf("Child process - Waiting for connections.\n");

	while( 1 ) {
		int sizeClient = sizeof( client );

		//The function stops here and does not release the command terminal to me. She doesn't run in background!
		printf("No problem here: 1.\n");
		if( ( descServer2 = accept( descServer1, ( struct sockaddr * )&client, &sizeClient ) ) == -1 ) {
			printf("Child process - Error: accept( ).\n");
			return;
		}
		printf("No problem here: 2.\n");
		int size;
		List *task = ( List * )malloc( sizeof( List ) );
		char *msgReceive = "Child process - task added with success.\n";
		size = recv( descServer2, task, sizeof( task ), 0 );
		if ( size < 0 ) {
			printf("Child process - Error: recv( ).\n");
			return;
		}

		no = add( no, task );
		showtasks( no );

		if( send( descServer2, msgReceive, strlen( msgReceive ), 0 ) < 0 ) {
			printf("Child process - Error: send( ).\n");
		}

	}
	close( descServer2 );
	return;
}

Was This Post Helpful? 0
  • +
  • -

#5 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 1112
  • View blog
  • Posts: 4,619
  • Joined: 09-June 09

Re: Question about interprocess communication. Sockets. Daemons.

Posted 01 July 2013 - 06:12 PM

Did you check the return code for the daemon call? The daemon system call actually forks the process, killing the parent, so there is no delay from the system call, if thats what you are thinking.

Try checking the return code for errors


if(daemon(0, 0)) {
   fprintf(stderr, "Daemon Error: %s\n", strerror(errno));
}


This post has been edited by jjl: 01 July 2013 - 06:12 PM

Was This Post Helpful? 1
  • +
  • -

#6 robgeek  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 104
  • Joined: 15-January 13

Re: Question about interprocess communication. Sockets. Daemons.

Posted 01 July 2013 - 08:20 PM

I put this piece of code on line 22, but i tried to use daemon(1, 1) as arguments first. The output was.
if( daemon( 1, 1 ) ) {// I tried (0, 0) too.
	fprintf(stderr, "Daemon Error: %s\n", strerror(errno));
}

Quote

Child process - Waiting for connections.
No problem here: 1.
No problem here: 1.


When i use, daemon(0, 0) i have no error message too.

Quote

Father - trying to connect.->This process I did not show on the topic, but i believe he is working.
Child process - task added with success.
Father - server connection terminated.

Note that when I use the daemon(0.0) the functions printf("No problem here: 1.\n"); and printf("No problem here: 2.\n");
not appear. I have no idea why.
Was This Post Helpful? 0
  • +
  • -

#7 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 1112
  • View blog
  • Posts: 4,619
  • Joined: 09-June 09

Re: Question about interprocess communication. Sockets. Daemons.

Posted 01 July 2013 - 10:32 PM

Quote

Note that when I use the daemon(0.0) the functions printf("No problem here: 1.\n"); and printf("No problem here: 2.\n");
not appear. I have no idea why.

When you put zero as the second argument to daemon, it redirects stdout, stderr, and stdin to /dev/null, so that type of behavior is expected.

Post your complete code we can have a better look at it.

Also explain a little more about your problem, what do you mean by release?

Quote

She stops in accept() funtion and does not release the command terminal to me.

Was This Post Helpful? 1
  • +
  • -

#8 robgeek  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 104
  • Joined: 15-January 13

Re: Question about interprocess communication. Sockets. Daemons.

Posted 02 July 2013 - 06:43 AM

Look. I have 6 files with multiple functions that do not present problems. If really needed I will post everything here. For now, I'll put only the part that is giving error.
The idea is create a task scheduler with the command in terminal:
./task_scheduler 12:34 23 task1
./task_scheduler 09:32 19 task2
...
The task_scheduler must be alive with a linked list which contain the tasks, i have to do other things with this list, but i have to solve this problem first. So, my idea is create a program that i compile with the name task_scheduler, and he creates a child process, and this process calls task_scheduler function, she will stay alive, like a server socket, waiting for new tasks. The parent process will be the client socket, he will send a node to his son, task_scheduler. This node contains ther arguments that i enter in my command terminal.
That's why i need the child process run in background. So he stay alive, and his parent can die, so i can enter with a new task, like ./task_scheduler 10:32 10 task3.
//Main program that i compile with the name "task_scheduler"
int main(int argc, char *argv[]) {
	int pfds[2];
	int signal; /* msg is just a signal, doesn't contain useful information */

	//He will continue running only if three parameters are passed.
	if( (argc-1) == 3 ) {
		if( timer( argv[1] ) && amount( argv[2] ) ) {
			printf("Parameters accepted.\n");
		}
	}
	else {
		printf("Passing invalid parameters.\n");
		return 1;
	}

	if( pipe( pfds ) == -1 ) {
		fprintf(stderr, "Pipe Error: %s\n", strerror(errno));
		return -1;
	}

	pid_t child_pid = fork();
	if( child_pid < 0 ){
		fprintf(stderr, "Child Process Could Not Be Created\n");
	}else if( child_pid == 0 ){
		if( daemon( 0, 0 ) ) {//Try to run in background.
			fprintf(stderr, "Daemon Error: %s\n", strerror(errno));
		}
		close( pfds[0] );
		task_scheduler( );//She will be the server, will stay alive in background.
		write( pfds[1], &signal, sizeof( signal ) );
		_exit( 0 );
	}
	else{
		close( pfds[1] );
		if( read( pfds[0], &signal, sizeof( signal ) ) == -1 ) { /* wait for signal */
			fprintf(stderr, "parent: read error\n");
		}
		else {
			List *task = taskCreate( argv[1], argv[2], argv[3] );//Create a node. No problems here.
			sendTask( task );//Send a node to task_scheduler and then, die, but task_scheduler will stay alive.
		}
	}

	return 0;
}

//She'll be waiting in the background to add new tasks to the list. From the point of view "socket", it is the server.
void task_scheduler( void ) {
	//If there is a SOCK_PATH, then there is a task_scheduler alive waiting for new nodes. Otherwise...
	if( !existFile( SOCK_PATH ) ) {//#define SOCK_PATH "socket_scheduler"
		//Create a list with head.
		List *node = ( List * )malloc( sizeof( List ) );
		node->task = NULL;		
		node->id = 0;
		node->hour = 0;
		node->min = 0;
		node->repetitions = 0;
		node->ant = NULL;
		node->prox = NULL;

		//Make the whole process of communication via socket.
		int descServer1, descServer2;
		struct sockaddr_un server, client;
		if( ( descServer1 = socket( AF_UNIX, SOCK_STREAM, 0 ) ) == -1 ) {
			perror("Child - Error: socket().\n");
			return;
		}

		memset( &server, 0, sizeof( struct sockaddr_un ) );
		server.sun_family = AF_UNIX;
		strcpy( server.sun_path, SOCK_PATH );
		//unlink( server.sun_path );

		if( bind( descServer1, ( struct sockaddr * )&server, sizeof( struct sockaddr_un ) ) == -1 ) {
			perror("Child - Error: bind()\n");
			return;
		}

		if( listen( descServer1, 5 ) == -1 ) {
			perror("Child - Error: listen( )\n");
			return;
		}

		printf("No problems here: 1.\n");
		
		//I'll make a funtion to remove the list and then kill task_scheduler.
		while( node != NULL ) {
			int clientSize = sizeof( client );
			printf("No problems here: 2.\n");
			if( ( descServer2 = accept( descServer1, ( struct sockaddr * )&client, &clientSize ) ) == -1 ) {
				perror("Child - Error: accept( ).\n");
				return;
			}
			printf("No problems here: 3.\n");
			int  size;
			List *task= ( List * )malloc( sizeof( List ) );
			char *msgReceived = "Child - Task added with success.\n";
			size = recv( descServer2, task, sizeof( task ), 0 );
			if ( size < 0 ) {
				perror("Child - Error: recv( ).\n");
				return;
			}

			node = addTask( node, task );
			showTasks( node );

			if( send( descServer2, msgReceived, strlen( msgReceived ), 0 ) < 0 ) {
				perror("Child - Error: send( ).\n");
			}

		}
		close( descServer2 );
		unlink( server.sun_path );
	}

	return;
}

//Sends a task to the process task_scheduler.
void sendTask( List *task) {
	
	int descClient1, descClient2, length;
	struct sockaddr_un client;

	if( ( descClient1 = socket( AF_UNIX, SOCK_STREAM, 0 ) ) == -1 ) {
		perror("Father - Error: socket.( ).\n");
		return;
	}

	client.sun_family = AF_UNIX;
	strcpy(client.sun_path, SOCK_PATH);
	length = strlen(client.sun_path) + sizeof(client.sun_family);
	if( connect( descClient1, ( struct sockaddr * )&client, length ) == -1 ) {
		perror("Father - Error: connect( ).\n");
		return;
	}

	if( send( descClient1, task, sizeof( task ), 0 ) == -1 ) {
		perror("Father - Error: send( ).\n");
		return;
	}

	char str[100];
	if( ( descClient2 = recv( descClient1, str, 100, 0 ) ) < 0 ) {
		perror("Father - Error: recv().\n");
		return;
	}

	str[descClient2] = '\0';
	printf("\n%s", str);
	close( descClient1 );

	return;
}

Was This Post Helpful? 0
  • +
  • -

#9 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1432
  • View blog
  • Posts: 4,968
  • Joined: 19-February 09

Re: Question about interprocess communication. Sockets. Daemons.

Posted 02 July 2013 - 12:01 PM

Hi, it appears you want to create a background (server) process/service, on the fly using a fork, if the server doesn't exist.


So in main something like :


int main(int argc, char *argv[]) 
{
  bool send_data = true;

  if( !existFile( SOCK_PATH )
  {
    /* fork() */

    /* if child */
    {
      /* create background server */
      task_scheduler();
      /* don't send the data from child */
      send_data = false; /* or handle exit */
    }
  }

  /* server should now exist */  
  if( send_data )
  {
    /* connect to server */
    /* send task data */
  }
 
  return 0; 
}


Was This Post Helpful? 1
  • +
  • -

#10 robgeek  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 104
  • Joined: 15-January 13

Re: Question about interprocess communication. Sockets. Daemons.

Posted 02 July 2013 - 07:01 PM

#define

I did what you said and did not work.
Was This Post Helpful? 0
  • +
  • -

#11 #define  Icon User is offline

  • Duke of Err
  • member icon

Reputation: 1432
  • View blog
  • Posts: 4,968
  • Joined: 19-February 09

Re: Question about interprocess communication. Sockets. Daemons.

Posted 02 July 2013 - 08:43 PM

I would be tempted to try a name on the root.

#define SOCK_PATH "/socket_scheduler"




Another way?
Linux Daemon Writing HOWTO
Was This Post Helpful? 1
  • +
  • -

#12 jjl  Icon User is offline

  • Engineer
  • member icon

Reputation: 1112
  • View blog
  • Posts: 4,619
  • Joined: 09-June 09

Re: Question about interprocess communication. Sockets. Daemons.

Posted 03 July 2013 - 12:35 AM

Yes I agree, using a named pipe will be easier to determine if the server is running. Just simply check if the named piped file is open, if so the server is running.
Was This Post Helpful? 1
  • +
  • -

#13 robgeek  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 104
  • Joined: 15-January 13

Re: Question about interprocess communication. Sockets. Daemons.

Posted 03 July 2013 - 08:40 AM

But i did this, guys.
My original "define" is:

Quote

#define SOCK_PATH "socket_scheduler"

He is creating a file with this name in the same folder where are all source files.

My problem is, with the code i posted in the post number #8 the process server is not letting the terminal free for me.
I posted what happen when i run the program here, in post #6.
Was This Post Helpful? 0
  • +
  • -

#14 robgeek  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 104
  • Joined: 15-January 13

Re: Question about interprocess communication. Sockets. Daemons.

Posted 03 July 2013 - 08:48 AM

When i put '/' in front of "socket_scheduler", like:

Quote

#define SOCK_PATH "/socket_scheduler"

I have a error in bind() function. Always.
Was This Post Helpful? 0
  • +
  • -

#15 robgeek  Icon User is offline

  • D.I.C Head

Reputation: 3
  • View blog
  • Posts: 104
  • Joined: 15-January 13

Re: Question about interprocess communication. Sockets. Daemons.

Posted 04 July 2013 - 04:45 PM

Guys, there is other way to make my server run in background?
I really have to use daemon( ) function? I'm trying to solve my problem but it's been really hard.
Was This Post Helpful? 0
  • +
  • -

  • (2 Pages)
  • +
  • 1
  • 2