+#include<pthread.h>+#include<semaphore.h>+#include<signal.h>+staticsem_tevent_sem;+staticvolatilesig_atomic_tintrested_event=0;++voidsig_handler_event1(intsig)+{+interested_event=1;+sem_post(&event_sem);+}+staticvoid*event_handler_thread_func()+{+while(1){+sem_wait(&event_sem);+if(intrested_event){+LOGD("%s,%d, received intrested_event signal.\n",__func__,__LINE__);+intrested_event=0;+}+}+pthread_exit(NULL);+}intmain(intargc,char*argv[])+pthread_tevent_thread;+if(pthread_create(&event_thread,NULL,event_handler_thread_func,NULL)!=0){printf("Thread create failed%s.\n",strerror(errno));+exit(1);+}+sem_init(&event_sem,0,0);+structsigactionusr_action;+sigset_tblock_mask;+sigfillset(&block_mask);+usr_action.sa_handler=sig_handler_event1;+usr_action.sa_mask=block_mask;//block all signal inside signal handler.+usr_action.sa_flags=SA_NODEFER;//do not block SIGUSR1 within sig_handler_int.+sigaction(SIGUSR1,&usr_action,NULL);+intfd=open("/dev/target_device_name",O_RDWR);+intmy_pid=getpid();+ioctl(fd,0x111,&my_pid);+close(fd);
A signal could interrupt below primitive calls:
close, fcntl (operation F_SETLK), open, read, recv, recvfrom, select, send, sendto, tcdrain, waitpid, wait, and write,
POXIS and BSD will handle this situation differently. POXIS will fail these primitive call with EINTR, caller need to use macro TEMP_FAILURE_RETRY (expression) to retry.
Programmer need to take care of this issue.
Reference:
Sending Signal Across Processes
In receiver process, create a share memory, write receiver’s pid to it, then wait for the signal.
+#include<signal.h>+#include<sys/ipc.h>+#include<sys/shm.h>+#include<pthread.h>+#include<semaphore.h>+#defineMY_IPC_KEY_PATH"/data/misc/bluedroid"+staticsem_tevent_sem;+staticvolatilesig_atomic_tintrested_event=0;++staticvoidsig_handler_int(intsig)+{+interested_event=1;+sem_post(&event_sem);+}++staticvoidwait_for_signal(void)+{+pid_tpid=getpid();+key_tmy_ipc_key=ftok(MY_IPC_KEY_PATH,'s');+intshare_mem_id=shmget(my_ipc_key,sizeof(pid_t),IPC_CREAT|0666);+pid_t*share_mem=(pid_t*)shmat(share_mem_id,NULL,0);+*share_mem=pid;++printf("%s,%d, set my pid %d\n",__func__,__LINE__,pid);++structsigactionusr_action;+sigset_tblock_mask;+sigfillset(&block_mask);+usr_action.sa_handler=sig_handler_int;+usr_action.sa_mask=block_mask;//block all signal inside signal handler.+usr_action.sa_flags=SA_NODEFER;//do not block SIGUSR1 within sig_handler_int.+sigaction(SIGINT,&usr_action,NULL);++sem_init(&event_sem,0,0);+while(intrested_event==0){+sem_wait(&event_sem);+if(intrested_event){+printf("%s,%d, received intrested_event signal.\n",__func__,__LINE__);+}+}+intrested_event=0;+shmdt(share_mem);+shmctl(share_mem_id,IPC_RMID,NULL);+}intreceiver_process(intargc,char*argv[]){+wait_for_signal();
In sender process, acquire the receiver process’spid through the share memory object, then send the signal.
+#include<signal.h>+#include<sys/ipc.h>+#include<sys/shm.h>+#defineMY_IPC_KEY_PATH"/data/misc/bluedroid"+staticvoidwakeup_receiver(void)+{+key_tmy_ipc_key;+intshare_mem_id;+pid_t*share_mem;+pid_tpid;++my_ipc_key=ftok(MY_IPC_KEY_PATH,'s');+share_mem_id=shmget(my_ipc_key,sizeof(pid_t),0666);+share_mem=(pid_t*)shmat(share_mem_id,NULL,0);+pid=*share_mem;+shmdt(share_mem);++if(pid>0){+intret=sigquue(pid,SIGINT,0);if(ret!=0){printf("send signal failed %s.\n",strerror(errno));return;}+printf("%s,%d, send signale to pid %d\n",__func__,__LINE__,pid);+}+else{+printf("%s,%d, pid %d not ready\n",__func__,__LINE__,pid);+}++}voidsender(void){+wakeup_receiver();}
A note: shmget() is not available in Android, so this is not a valid IPC for Android.
Reference:
Footnote: signal lost
1 unreliable signal:
earlier version of UNIX signal is unreliable
2 real-time signal:
POSIX added signals, and
3 signal lost:
. when signal handler is running, blocked signals is “lost” (?!)
. when signal handler is running, the same signal is blocked by default, add SA_NODEFER in sigaction.sa_flags unblock it.