From f216a409197724504799ee59720f9ee19e84060c Mon Sep 17 00:00:00 2001
From: Guo Wenxue <guowenxue@gmail.com>
Date: Thu, 15 Nov 2018 13:32:48 +0800
Subject: [PATCH] Update ch3_fork a small bug, and add pthread sample code

---
 ch4_thread/daemon.c               |   32 +++
 ch4_thread/thread.c               |  103 ++++++++++
 ch4_thread/socket_server_thread.c |  203 ++++++++++++++++++++
 ch3_fork/socket_server.c          |    2 
 ch4_thread/thread_lock.c          |  123 ++++++++++++
 ch4_thread/signal.c               |  105 ++++++++++
 6 files changed, 567 insertions(+), 1 deletions(-)

diff --git a/ch3_fork/socket_server.c b/ch3_fork/socket_server.c
index 875386c..3780019 100644
--- a/ch3_fork/socket_server.c
+++ b/ch3_fork/socket_server.c
@@ -142,7 +142,7 @@
 			rv=write(clifd, MSG_STR, strlen(MSG_STR));
 		       	if(rv < 0)
 		       	{
-			       	printf("Write to client by sockfd[%d] failure: %s\n", sockfd, strerror(errno));
+			       	printf("Write to client by sockfd[%d] failure: %s\n", clifd, strerror(errno));
 			       	close(clifd);
 				exit(0);
 		       	}
diff --git a/ch4_thread/daemon.c b/ch4_thread/daemon.c
new file mode 100644
index 0000000..1a03c09
--- /dev/null
+++ b/ch4_thread/daemon.c
@@ -0,0 +1,32 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <syslog.h>
+#include <libgen.h> /* basename() */
+
+int main(int argc, char **argv)
+{
+    char      *progname = basename(argv[0]);
+
+    if( daemon(0, 0) < 0)
+    {
+	    printf("Program daemon() failure: %s\n", strerror(errno));
+	    return -1;
+    }
+    openlog("daemon", LOG_CONS | LOG_PID, 0);
+    syslog(LOG_NOTICE,  "Program '%s'start running\n",  progname);
+    syslog(LOG_WARNING,  "Program '%s' running with a warnning message\n",  progname );
+    syslog(LOG_EMERG,  "Program '%s' running with a emergency message\n",  progname );
+    while(1)
+    {
+         //Do Something here
+         ;
+    }
+
+    syslog(LOG_NOTICE,  "Program '%s' stop running\n",  progname);
+    closelog();
+
+    return 0;
+}
diff --git a/ch4_thread/signal.c b/ch4_thread/signal.c
new file mode 100644
index 0000000..37bddba
--- /dev/null
+++ b/ch4_thread/signal.c
@@ -0,0 +1,105 @@
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <execinfo.h>
+
+int         g_sigstop = 0; 
+
+void signal_stop(int signum)
+{
+	if( SIGTERM == signum )
+	{
+		printf("SIGTERM signal detected\n");
+	}
+	else if( SIGALRM == signum )
+	{
+		printf("SIGALRM signal detected\n");
+		g_sigstop = 1;
+	}
+}
+
+void signal_user(int signum)
+{
+	if(SIGUSR1 == signum)
+	{
+		printf("SIGUSR1 signal detected\n");
+	}
+	else if(SIGUSR2 == signum)
+	{
+		printf("SIGUSR2 signal detected\n");
+	}
+
+	g_sigstop = 1;
+}
+
+void signal_code(int signum)
+{
+	if(SIGBUS == signum)
+	{
+		printf("SIGBUS signal detected\n");
+	}
+	else if(SIGILL == signum)
+	{
+		printf("SIGILL signal detected\n");
+	}
+	else if(SIGSEGV == signum)
+	{
+		printf("SIGSEGV signal detected\n");
+	}
+
+	exit(-1);
+}
+
+int main(int argc, char **argv)
+{
+	char                 *ptr=NULL;
+	struct sigaction      sigact, sigign;
+
+	/*+--------------------------------------+
+	 *| Method1: Use signal() install signal |
+	 *+--------------------------------------+*/
+
+	signal(SIGTERM, signal_stop);
+	signal(SIGALRM, signal_stop);
+
+	signal(SIGBUS, signal_code);
+	signal(SIGILL, signal_code);
+	signal(SIGSEGV, signal_code);
+
+	/*+-----------------------------------------+
+	 *| Method2: Use sigaction() install signal |
+	 *+-----------------------------------------+*/
+
+	/*  Initialize the catch signal structure. */
+       	sigemptyset(&sigact.sa_mask);
+       	sigact.sa_flags = 0;
+       	sigact.sa_handler = signal_user;
+
+	/*  Setup the ignore signal. */
+       	sigemptyset(&sigign.sa_mask);
+       	sigign.sa_flags = 0;
+       	sigign.sa_handler = SIG_IGN; 
+	
+	sigaction(SIGINT, &sigign, 0); /*  ignore SIGINT signal by CTRL+C */
+
+       	sigaction(SIGUSR1,  &sigact, 0); /*  catch SIGUSR1 */
+       	sigaction(SIGUSR2,  &sigact, 0); /*  catch SIGUSR1 */
+
+
+	printf("Program start running for 20 seconds...\n");
+	alarm(20);
+
+	while( !g_sigstop )
+	{
+		;
+	}
+
+	printf("Program start stop running...\n");
+
+	printf("Invalid pointer operator will raise SIGSEGV signal\n");
+	*ptr = 'h';
+
+	return 0;
+}
diff --git a/ch4_thread/socket_server_thread.c b/ch4_thread/socket_server_thread.c
new file mode 100644
index 0000000..7b194af
--- /dev/null
+++ b/ch4_thread/socket_server_thread.c
@@ -0,0 +1,203 @@
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h> 
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <stdlib.h>
+#include <getopt.h>
+#include <pthread.h>
+
+#define MSG_STR "Hello LingYun IoT Studio Client\n"
+
+typedef void *(THREAD_BODY) (void *thread_arg);
+
+void *thread_worker(void *ctx);
+int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg);
+
+
+void print_usage(char *progname)
+{
+	printf("%s usage: \n", progname);
+	printf("-p(--port): sepcify server listen port.\n");
+	printf("-h(--Help): print this help information.\n");
+
+	return ;
+}
+
+
+int main(int argc, char **argv)
+{
+	int                  sockfd = -1;
+	int                  rv = -1;
+	struct sockaddr_in   servaddr;
+	struct sockaddr_in   cliaddr;
+	socklen_t            len;
+	int                  port = 0;
+	int                  clifd;
+	int                  ch;
+	int                  on = 1;
+	pthread_t            tid;
+
+       	struct option        opts[] = {
+		{"port", required_argument, NULL, 'p'},
+		{"help", no_argument, NULL, 'h'},
+		{NULL, 0, NULL, 0}
+	};
+
+	while( (ch=getopt_long(argc, argv, "p:h", opts, NULL)) != -1 ) 
+	{
+		switch(ch)
+		{
+			case 'p':
+				port=atoi(optarg);
+				break;
+
+			case 'h':
+				print_usage(argv[0]);
+				return 0;
+		}
+
+	}
+
+	if( !port )
+	{
+		print_usage(argv[0]);
+		return 0;
+	}
+
+	sockfd=socket(AF_INET, SOCK_STREAM, 0);
+	if(sockfd < 0)
+	{
+		printf("Create socket failure: %s\n", strerror(errno));
+		return -1;
+	}
+	printf("Create socket[%d] successfully!\n", sockfd);
+
+	setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
+	memset(&servaddr, 0, sizeof(servaddr));
+	servaddr.sin_family=AF_INET;
+	servaddr.sin_port = htons(port);
+	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
+	//inet_aton("192.168.0.16", &servaddr.sin_addr);
+
+	rv=bind(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr));
+	if(rv < 0)
+	{
+		printf("Socket[%d] bind on port[%d] failure: %s\n", sockfd, port, strerror(errno));
+		return -2;
+	}
+
+	listen(sockfd, 13);
+	printf("Start to listen on port [%d]\n", port);
+
+	while(1)
+	{ 
+		printf("Start accept new client incoming...\n");
+
+		clifd=accept(sockfd, (struct sockaddr *)&cliaddr, &len);
+		if(clifd < 0)
+		{
+			printf("Accept new client failure: %s\n", strerror(errno));
+			continue;
+		}
+
+		printf("Accept new client[%s:%d] successfully\n", inet_ntoa(cliaddr.sin_addr), ntohs(cliaddr.sin_port));
+
+		thread_start(&tid, thread_worker, &clifd);
+	}
+
+
+	close(sockfd);
+
+	return 0;
+}
+
+int thread_start(pthread_t * thread_id, THREAD_BODY * thread_workbody, void *thread_arg)
+{
+	int                 rv = -1;
+	pthread_attr_t      thread_attr; 
+
+	if( pthread_attr_init(&thread_attr) )
+       	{
+	       	printf("pthread_attr_init() failure: %s\n", strerror(errno));
+		goto CleanUp;
+       	} 
+	
+	if( pthread_attr_setstacksize(&thread_attr, 120*1024) )
+       	{
+	       	printf("pthread_attr_setstacksize() failure: %s\n", strerror(errno));
+		goto CleanUp;
+	} 
+	
+	if( pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) )
+       	{
+	       	printf("pthread_attr_setdetachstate() failure: %s\n", strerror(errno));
+		goto CleanUp;
+       	} 
+	
+	/* Create the thread */
+       	if( pthread_create(thread_id, &thread_attr, thread_workbody, thread_arg) )
+	{
+		printf("Create thread failure: %s\n", strerror(errno));
+	       	goto CleanUp;
+	}
+
+	rv = 0;
+						    
+CleanUp:
+       
+	/* Destroy the  attributes  of  thread */ 
+	pthread_attr_destroy(&thread_attr); 
+	return rv;
+}
+
+void *thread_worker(void *ctx)
+{
+	int                  clifd;
+	int                  rv;
+       	char                 buf[1024]; 
+
+	if( !ctx )
+	{
+		printf("Invalid input arguments in %s()\n", __FUNCTION__);
+		pthread_exit(NULL);
+	}
+
+	clifd = *(int *)ctx;
+	
+	printf("Child thread start to commuicate with socket client...\n");
+	
+	while(1)
+	{ 
+		memset(buf, 0, sizeof(buf));
+	       	rv=read(clifd, buf, sizeof(buf));
+	       	if( rv < 0)
+	       	{
+		       	printf("Read data from client sockfd[%d] failure: %s\n", clifd, strerror(errno));
+		       	close(clifd);
+		       	pthread_exit(NULL);
+	       	}
+		else if( rv == 0)
+	       	{ 
+			printf("Socket[%d] get disconnected\n", clifd);
+		       	close(clifd);
+		       	pthread_exit(NULL);
+	       	} 
+		else if( rv > 0 ) 
+		{
+		       	printf("Read %d bytes data from Server: %s\n", rv, buf);
+	       	}
+	       
+		rv=write(clifd, buf, rv);
+	       	if(rv < 0)
+	       	{
+		       	printf("Write to client by sockfd[%d] failure: %s\n", clifd, strerror(errno));
+		       	close(clifd);
+		       	pthread_exit(NULL);
+	       	}
+	}
+}
+
diff --git a/ch4_thread/thread.c b/ch4_thread/thread.c
new file mode 100644
index 0000000..2e5b8fa
--- /dev/null
+++ b/ch4_thread/thread.c
@@ -0,0 +1,103 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+void *thread_worker1(void *args);
+void *thread_worker2(void *args);
+
+int main(int argc, char **argv)
+{
+	int              shared_var = 1000;
+	pthread_t        tid;
+	pthread_attr_t   thread_attr; 
+
+
+	if( pthread_attr_init(&thread_attr) )
+	{
+		printf("pthread_attr_init() failure: %s\n", strerror(errno));
+		return -1;
+	}
+
+	if( pthread_attr_setstacksize(&thread_attr, 120*1024) )
+	{
+		printf("pthread_attr_setstacksize() failure: %s\n", strerror(errno));
+		return -1;
+	}
+
+	if( pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) )
+	{
+		printf("pthread_attr_setdetachstate() failure: %s\n", strerror(errno));
+		return -1;
+	}
+
+	pthread_create(&tid, &thread_attr, thread_worker1, &shared_var);
+	printf("Thread worker1 tid[%ld] created ok\n", tid);
+
+	pthread_create(&tid, NULL, thread_worker2, &shared_var);
+	printf("Thread worker2 tid[%ld] created ok\n", tid);
+
+	pthread_attr_destroy(&thread_attr); 
+
+	/* Wait until  thread worker2 exit() */
+	pthread_join(tid, NULL);
+
+
+	while(1)
+	{
+		printf("Main/Control thread shared_var: %d\n", shared_var);
+		sleep(10);
+	}
+}
+
+void *thread_worker1(void *args)
+{
+	int            *ptr = (int *)args;
+
+	if( !args )
+	{
+		printf("%s() get invalid arguments\n", __FUNCTION__);
+	       	pthread_exit(NULL);
+	}
+
+	printf("Thread workder 1 [%ld] start running...\n", pthread_self());
+
+	while(1)
+	{
+		printf("+++: %s before shared_var++: %d\n", __FUNCTION__, *ptr);
+		*ptr += 1;
+		sleep(2);
+		printf("+++: %s after sleep shared_var: %d\n", __FUNCTION__, *ptr);
+	}
+
+	printf("Thread workder 1 exit...\n");
+
+	return NULL;
+}
+
+void *thread_worker2(void *args)
+{
+	int            *ptr = (int *)args;
+
+	if( !args )
+	{
+		printf("%s() get invalid arguments\n", __FUNCTION__);
+	       	pthread_exit(NULL);
+	}
+
+	printf("Thread workder 2 [%ld] start running...\n", pthread_self());
+
+	while(1)
+	{
+		printf("---: %s before shared_var++: %d\n", __FUNCTION__, *ptr);
+		*ptr += 1;
+		sleep(2);
+		printf("---: %s after sleep shared_var: %d\n", __FUNCTION__, *ptr);
+	}
+
+	printf("Thread workder 2 exit...\n");
+
+	return NULL;
+}
diff --git a/ch4_thread/thread_lock.c b/ch4_thread/thread_lock.c
new file mode 100644
index 0000000..b04f3d5
--- /dev/null
+++ b/ch4_thread/thread_lock.c
@@ -0,0 +1,123 @@
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+
+void *thread_worker1(void *args);
+void *thread_worker2(void *args);
+
+typedef struct worker_ctx_s
+{
+	int               shared_var;
+	pthread_mutex_t   lock;
+} worker_ctx_t;
+
+int main(int argc, char **argv)
+{
+	worker_ctx_t     worker_ctx;
+	pthread_t        tid;
+	pthread_attr_t   thread_attr; 
+
+	worker_ctx.shared_var = 1000;
+	pthread_mutex_init(&worker_ctx.lock, NULL);
+
+
+	if( pthread_attr_init(&thread_attr) )
+	{
+		printf("pthread_attr_init() failure: %s\n", strerror(errno));
+		return -1;
+	}
+
+	if( pthread_attr_setstacksize(&thread_attr, 120*1024) )
+	{
+		printf("pthread_attr_setstacksize() failure: %s\n", strerror(errno));
+		return -1;
+	}
+
+	if( pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED) )
+	{
+		printf("pthread_attr_setdetachstate() failure: %s\n", strerror(errno));
+		return -1;
+	}
+
+	pthread_create(&tid, &thread_attr, thread_worker1, &worker_ctx);
+	printf("Thread worker1 tid[%ld] created ok\n", tid);
+
+	pthread_create(&tid, &thread_attr, thread_worker2, &worker_ctx);
+	printf("Thread worker2 tid[%ld] created ok\n", tid);
+
+	while(1)
+	{
+		printf("Main/Control thread shared_var: %d\n", worker_ctx.shared_var);
+		sleep(10);
+	}
+
+	pthread_mutex_destroy(&worker_ctx.lock);
+}
+
+void *thread_worker1(void *args)
+{
+	worker_ctx_t        *ctx = (worker_ctx_t *)args;
+
+	if( !args )
+	{
+		printf("%s() get invalid arguments\n", __FUNCTION__);
+	       	pthread_exit(NULL);
+	}
+
+	printf("Thread workder 1 [%ld] start running...\n", pthread_self());
+
+	while(1)
+	{
+		pthread_mutex_lock(&ctx->lock);
+
+		printf("+++: %s before shared_var++: %d\n", __FUNCTION__, ctx->shared_var);
+		ctx->shared_var ++;
+		sleep(2);
+		printf("+++: %s after sleep shared_var: %d\n", __FUNCTION__, ctx->shared_var);
+
+		pthread_mutex_unlock(&ctx->lock);
+
+		sleep(1);
+	}
+
+	printf("Thread workder 1 exit...\n");
+
+	return NULL;
+}
+
+void *thread_worker2(void *args)
+{
+	worker_ctx_t        *ctx = (worker_ctx_t *)args;
+
+	if( !args )
+	{
+		printf("%s() get invalid arguments\n", __FUNCTION__);
+	       	pthread_exit(NULL);
+	}
+
+	printf("Thread workder 2 [%ld] start running...\n", pthread_self());
+
+	while(1)
+	{
+		if(0 != pthread_mutex_trylock(&ctx->lock) )
+		{
+			continue;
+		}
+
+		printf("---: %s before shared_var++: %d\n", __FUNCTION__, ctx->shared_var);
+		ctx->shared_var ++;
+		sleep(2);
+		printf("---: %s after sleep shared_var: %d\n", __FUNCTION__, ctx->shared_var);
+
+		pthread_mutex_unlock(&ctx->lock);
+
+		sleep(1);
+	}
+
+	printf("Thread workder 2 exit...\n");
+
+	return NULL;
+}

--
Gitblit v1.9.1