How to listen to multiple sources?

My app should listen to ttyS1 device, some TCP port and do some scheduled tasks (listen to system clock).

How can I do this multitasking?
select() is used to monitor multiple file descriptors at once.

I'm not sure what "listen to system clock" means.
It means - do some scheduled tasks. Like: exactly at 12:37:21 request data from temperature sensor. Something like interrupts, when system clock reaches some certain value.
Only way I can think of is:

1) make parent process which will handle all the data
|
+--> 2) fork a child which will take care of ttyS
|
+--> 3) fork a child which will communicate with TCP port
|
+--> 4) fork a child which will handle timing

connect all these to parent with pipes

then loop forever parent parent process
and finally parent deals with all incoming data, registering connections, logging etc...
thunder87l -- way overkill. This can all be done with select().

Before calling select(), compute the amount of time until the need scheduled task. Store this in a struct timeval, which you then pass a pointer to to select() as the last parameter. select() will return when a) any of the file descriptors change status (read status if you put them in the read_fd set) or when the timeout expires. select() returns -1 on error, 0 on timeout, or the number of file descriptors (>0) that changed status.

I just never used forks and pipes, so I gave it a try:
Now I see that there was absolutely no need for TCP or serial process. Still I want to finish with this before trying to make better one.

So this code basically forks three children: scheduler, tcp and serial. Each one has 1 input and 1 output pipe to parent. If parent dies - they all die. Idea of this test is for parent to send children "Hello World!" string through output pipes. Children loop this string back to parent through other pipe.

Problem is - I send 12 char string, and I get back 14 characters . I marked problematic place with bold. >>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
#include <iostream>
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <signal.h>
#include <linux/prctl.h>
#include <sys/prctl.h>
#include <cstring>
#include <termios.h>
#include <fcntl.h>
#include <sys/signal.h>
using namespace std;

int main(void)
{
pid_t main_pid, serial_pid, tcp_pid, scheduler_pid;
int status;
char line[100];

int pipe_serial_1[2];
status = pipe2(pipe_serial_1,O_NONBLOCK);
if (status == -1)
	{
	cout<<"Error: could not open pipe (main->serial) for serial loop."<<endl;
	return 0;
	}

int pipe_serial_2[2];
status = pipe2(pipe_serial_2,O_NONBLOCK);
if (status == -1)
	{
	cout<<"Error: could not open pipe (serial->main) for serial loop."<<endl;
	return 0;
	}

serial_pid = fork();

if (serial_pid == -1)
	{
	cout<<"Error: could not fork serial loop."<<endl;
	return 0;
	}

if (serial_pid ==  0) //serial loop
	{
	cout<<"Serial process started."<<endl;
	close(pipe_serial_2[0]);
	close(pipe_serial_1[1]);
	prctl(PR_SET_PDEATHSIG, SIGTERM);
	while(1)
		{
		usleep(100);
		status=read(pipe_serial_1[0], line, 100);
		if (status!=-1)
			{
			cout<<"SERIAL: redirecting: "<<line<<endl;
			write(pipe_serial_2[1], line, strlen(line));
			}
		}
	_exit(0);
	}

else
	{
	close(pipe_serial_2[1]);
	close(pipe_serial_1[0]);
	}

int pipe_tcp_1[2];
status = pipe2(pipe_tcp_1,O_NONBLOCK);
if (status == -1)
	{
	cout<<"Error: could not open pipe (main->tcp) for tcp loop."<<endl;
	kill(serial_pid, SIGTERM);
	return 0;
	}

int pipe_tcp_2[2];
status = pipe2(pipe_tcp_2,O_NONBLOCK);
if (status == -1)
	{
	cout<<"Error: could not open pipe (tcp->main) for tcp loop."<<endl;
	kill(serial_pid, SIGTERM);
	return 0;
	}

tcp_pid = fork();

if (tcp_pid == -1)
	{
	cout<<"Error: could not fork tcp loop."<<endl;
	kill(serial_pid, SIGTERM);
	return 0;
	}

if (tcp_pid ==  0) //tcp loop
	{
	cout<<"TCP process started."<<endl;
	close(pipe_serial_2[0]);
	close(pipe_serial_1[1]);
	close(pipe_tcp_2[0]);
	close(pipe_tcp_1[1]);
	prctl(PR_SET_PDEATHSIG, SIGTERM);
	while(1)
		{
		usleep(100);
		status=read(pipe_tcp_1[0], line, 100);
		if (status!=-1)
			{
			cout<<"TCP: redirecting: "<<line<<endl;
			write(pipe_tcp_2[1], line, strlen(line));
			}
		
		}
	_exit(0);
	}

else
	{
	close(pipe_tcp_2[1]);
	close(pipe_tcp_1[0]);
	}

int pipe_scheduler_1[2];
status = pipe2(pipe_scheduler_1,O_NONBLOCK);
if (status == -1)
	{
	cout<<"Error: could not open pipe (main->scheduler) for scheduler loop."<<endl;
	kill(serial_pid, SIGTERM);
	kill(tcp_pid, SIGTERM);
	return 0;
	}

int pipe_scheduler_2[2];
status = pipe2(pipe_scheduler_2,O_NONBLOCK);
if (status == -1)
	{
	cout<<"Error: could not open pipe (scheduler->main) for scheduler loop."<<endl;
	kill(serial_pid, SIGTERM);
	kill(tcp_pid, SIGTERM);
	return 0;
	}

scheduler_pid = fork();

if (scheduler_pid == -1)
	{
	cout<<"Error: could not fork scheduler loop."<<endl;
	kill(serial_pid, SIGTERM);
	kill(tcp_pid, SIGTERM);
	return 0;
	}

if (scheduler_pid ==  0)
	{
	cout<<"Scheduler process started."<<endl;
	close(pipe_tcp_2[0]);
	close(pipe_tcp_1[1]);
	close(pipe_scheduler_2[0]);
	close(pipe_scheduler_1[1]);
	prctl(PR_SET_PDEATHSIG, SIGTERM);
	while(1)
		{
		usleep(100);
		status=read(pipe_scheduler_1[0], line, 100);
		if (status!=-1)
			{
			cout<<"SCHEDULER: redirecting: "<<line<<endl;
			write(pipe_scheduler_2[1], line, strlen(line));
			}
		
		}
	_exit(0);
	}

else
	{
	close(pipe_scheduler_2[1]);
	close(pipe_scheduler_1[0]);
	}

main_pid=getpid();
cout<<"Main process started."<<endl;
cout<<"Main PID:      "<<main_pid<<endl;
cout<<"Serial PID:    "<<serial_pid<<endl;
cout<<"TCP PID:       "<<tcp_pid<<endl;
cout<<"Scheduler PID: "<<scheduler_pid<<endl;

int x=0;

while (1)
{
usleep(100);
x++;
	if (x==13000)
	{
	strcpy(line,"Hello World!");
	cout<<"MAIN: sending message."<<endl;
	write(pipe_serial_1[1], line, strlen(line));
	write(pipe_tcp_1[1], line, strlen(line));
	write(pipe_scheduler_1[1], line, strlen(line));
	x=0;
	}

	status=read(pipe_serial_2[0], line, 100);
	if (status!=-1) {cout<<"MAIN: received from serial   : "<<line<<endl;}
	status=read(pipe_tcp_2[0], line, 100);
	if (status!=-1) {cout<<"MAIN: received from tcp      : "<<line<<endl;}
	status=read(pipe_scheduler_2[0], line, 100);
	if (status!=-1) {cout<<"MAIN: received from scheduler: "<<line<<endl;}

}

kill(serial_pid, SIGTERM);
kill(tcp_pid, SIGTERM);
kill(scheduler_pid, SIGTERM);
return 0;

}


See, if I rewrite this piece:
if (status!=-1) {cout<<"MAIN: received from serial : "<<line<<endl;}
like that:
if (status!=-1) {cout<<"MAIN: received from serial : "<<line<<endl; cout<<strlen(line)<<endl;}
i get strlen(line) = 14 chars, and this kind of messages:
MAIN: sending message.
SCHEDULER: redirecting: Hello World!��
TCP: redirecting: Hello World!��
MAIN: received from scheduler: Hello World!��
SERIAL: redirecting: Hello World!��
MAIN: received from serial   : Hello World!��
14
MAIN: received from tcp      : Hello World!��


But if I change it to this:
if (status!=-1) {cout<<"MAIN: received from serial : "<<strlen(line)<<endl;}
suddenly it's already 12 chars and no junk:
MAIN: sending message.
TCP: redirecting: Hello World!
SCHEDULER: redirecting: Hello World!
SERIAL: redirecting: Hello World!
MAIN: received from serial   : Hello World!12
MAIN: received from tcp      : Hello World!
MAIN: received from scheduler: Hello World!


How is this possible? How measuring of string length in parent process output can affect what child process puts to tty?
It seems that "!" char in the "Hello World!" was causing all problems. As soon as I got rid of it - everything started working just fine. I wonder what king of bug this is?

I checked those junk characters. If I read only one of them, like cout<<(int)line[13]<<endl; They both seemed to be -1.
If I read them both, like cout<<(int)line[12]<<(int)line(13)<<endl; They appeared as "00". Never seen anything like this.
Topic archived. No new replies allowed.