How to send signal to a child process created via fork and execl? - process

Assume I have a program foo that simply prints forever but is stopped before then,
int main(int argc, char * argv[])
{
kill(getpid(), SIGSTOP);
while(1) {
printf("foo\n");
}
return 0;
}
And then I have a program bar that forks and runs foo:
int main(int argc, char * argv[])
{
pid_t pid = fork();
if (pid == 0)
{
execl("foo", "foo", NULL);
}
return 0;
}
Now, I want bar to be able to send SIGCONT to foo so it can go on its printing duties, and then later send SIGSTOP again, and even later send SIGCONT again, and so on.
I couldn't figure out how to do that. Any help?
EDIT: I figured out my problem. Apparently, the foo program isn't ready to accept signals immediately when it runs. When I did
sleep(5);
int rc = kill(pid, SIGCONT);
it worked.

pid_t pid = fork();
if (pid == 0)
{
execl("foo", "foo", NULL);
}
int rc = kill(pid, 18);
return 0;

Suggest: don't forget to handle errors codes from system calls! Work without handling of error codes is worse style! This two actions you can do in one program. In this case it's will be more effective:
#include <errno.h>
int main(int argc, char * argv[])
{
int rc = 0;
pid_t pid = fork();
if (pid == 0) /* child */
{
kill(getpid(), SIGSTOP);
if (rc == -1) {
perror("Something wrong while kill() in child");
}
while (1) {
printf("foo\n");
}
} else if (pid > 0) { /* father */
rc = kill(pid, SIGCONT);
if (rc == -1) {
perror("Something wrong while kill() in parent");
}
} else if (pid < 0) {
perror("Something wrong while fork()");
return -1;
}
return 0;
}

Related

How to change this app to disable input from command line?

This is the Original code:
#include <stdio.h>
#include <string.h>
#include <assert.h>
#if defined(_WIN32) && !defined(__CYGWIN__)
#include <windows.h>
#else
#include <sys/select.h>
#endif
#include <sphinxbase/err.h>
#include <sphinxbase/ad.h>
#include "pocketsphinx.h"
static const arg_t cont_args_def[] = {
POCKETSPHINX_OPTIONS,
/* Argument file. */
{"-argfile",
ARG_STRING,
NULL,
"Argument file giving extra arguments."},
{"-adcdev",
ARG_STRING,
NULL,
"Name of audio device to use for input."},
{"-infile",
ARG_STRING,
NULL,
"Audio file to transcribe."},
{"-inmic",
ARG_BOOLEAN,
"no",
"Transcribe audio from microphone."},
{"-time",
ARG_BOOLEAN,
"no",
"Print word times in file transcription."},
CMDLN_EMPTY_OPTION
};
static ps_decoder_t *ps;
static cmd_ln_t *config;
static FILE *rawfd;
static void
print_word_times()
{
int frame_rate = cmd_ln_int32_r(config, "-frate");
ps_seg_t *iter = ps_seg_iter(ps);
while (iter != NULL) {
int32 sf, ef, pprob;
float conf;
ps_seg_frames(iter, &sf, &ef);
pprob = ps_seg_prob(iter, NULL, NULL, NULL);
conf = logmath_exp(ps_get_logmath(ps), pprob);
printf("%s %.3f %.3f %f\n", ps_seg_word(iter), ((float)sf / frame_rate),
((float) ef / frame_rate), conf);
iter = ps_seg_next(iter);
}
}
static int
check_wav_header(char *header, int expected_sr)
{
int sr;
if (header[34] != 0x10) {
E_ERROR("Input audio file has [%d] bits per sample instead of 16\n", header[34]);
return 0;
}
if (header[20] != 0x1) {
E_ERROR("Input audio file has compression [%d] and not required PCM\n", header[20]);
return 0;
}
if (header[22] != 0x1) {
E_ERROR("Input audio file has [%d] channels, expected single channel mono\n", header[22]);
return 0;
}
sr = ((header[24] & 0xFF) | ((header[25] & 0xFF) << 8) | ((header[26] & 0xFF) << 16) | ((header[27] & 0xFF) << 24));
if (sr != expected_sr) {
E_ERROR("Input audio file has sample rate [%d], but decoder expects [%d]\n", sr, expected_sr);
return 0;
}
return 1;
}
/*
* Continuous recognition from a file
*/
static void
recognize_from_file()
{
int16 adbuf[2048];
const char *fname;
const char *hyp;
int32 k;
uint8 utt_started, in_speech;
int32 print_times = cmd_ln_boolean_r(config, "-time");
fname = cmd_ln_str_r(config, "-infile");
if ((rawfd = fopen(fname, "rb")) == NULL) {
E_FATAL_SYSTEM("Failed to open file '%s' for reading",
fname);
}
if (strlen(fname) > 4 && strcmp(fname + strlen(fname) - 4, ".wav") == 0) {
char waveheader[44];
fread(waveheader, 1, 44, rawfd);
if (!check_wav_header(waveheader, (int)cmd_ln_float32_r(config, "-samprate")))
E_FATAL("Failed to process file '%s' due to format mismatch.\n", fname);
}
if (strlen(fname) > 4 && strcmp(fname + strlen(fname) - 4, ".mp3") == 0) {
E_FATAL("Can not decode mp3 files, convert input file to WAV 16kHz 16-bit mono before decoding.\n");
}
ps_start_utt(ps);
utt_started = FALSE;
while ((k = fread(adbuf, sizeof(int16), 2048, rawfd)) > 0) {
ps_process_raw(ps, adbuf, k, FALSE, FALSE);
in_speech = ps_get_in_speech(ps);
if (in_speech && !utt_started) {
utt_started = TRUE;
}
if (!in_speech && utt_started) {
ps_end_utt(ps);
hyp = ps_get_hyp(ps, NULL);
if (hyp != NULL)
printf("%s\n", hyp);
if (print_times)
print_word_times();
fflush(stdout);
ps_start_utt(ps);
utt_started = FALSE;
}
}
ps_end_utt(ps);
if (utt_started) {
hyp = ps_get_hyp(ps, NULL);
if (hyp != NULL) {
printf("%s\n", hyp);
if (print_times) {
print_word_times();
}
}
}
fclose(rawfd);
}
/* Sleep for specified msec */
static void
sleep_msec(int32 ms)
{
#if (defined(_WIN32) && !defined(GNUWINCE)) || defined(_WIN32_WCE)
Sleep(ms);
#else
/* ------------------- Unix ------------------ */
struct timeval tmo;
tmo.tv_sec = 0;
tmo.tv_usec = ms * 1000;
select(0, NULL, NULL, NULL, &tmo);
#endif
}
/*
* Main utterance processing loop:
* for (;;) {
* start utterance and wait for speech to process
* decoding till end-of-utterance silence will be detected
* print utterance result;
* }
*/
static void
recognize_from_microphone()
{
ad_rec_t *ad;
int16 adbuf[2048];
uint8 utt_started, in_speech;
int32 k;
char const *hyp;
if ((ad = ad_open_dev(cmd_ln_str_r(config, "-adcdev"),
(int) cmd_ln_float32_r(config,
"-samprate"))) == NULL)
E_FATAL("Failed to open audio device\n");
if (ad_start_rec(ad) < 0)
E_FATAL("Failed to start recording\n");
if (ps_start_utt(ps) < 0)
E_FATAL("Failed to start utterance\n");
utt_started = FALSE;
E_INFO("Ready....\n");
for (;;) {
if ((k = ad_read(ad, adbuf, 2048)) < 0)
E_FATAL("Failed to read audio\n");
ps_process_raw(ps, adbuf, k, FALSE, FALSE);
in_speech = ps_get_in_speech(ps);
if (in_speech && !utt_started) {
utt_started = TRUE;
E_INFO("Listening...\n");
}
if (!in_speech && utt_started) {
/* speech -> silence transition, time to start new utterance */
ps_end_utt(ps);
hyp = ps_get_hyp(ps, NULL );
if (hyp != NULL) {
printf("%s\n", hyp);
fflush(stdout);
}
if (ps_start_utt(ps) < 0)
E_FATAL("Failed to start utterance\n");
utt_started = FALSE;
E_INFO("Ready....\n");
}
sleep_msec(100);
}
ad_close(ad);
}
int
main(int argc, char *argv[])
{
char const *cfg;
config = cmd_ln_parse_r(NULL, cont_args_def, argc, argv, TRUE);
/* Handle argument file as -argfile. */
if (config && (cfg = cmd_ln_str_r(config, "-argfile")) != NULL) {
config = cmd_ln_parse_file_r(config, cont_args_def, cfg, FALSE);
}
if (config == NULL || (cmd_ln_str_r(config, "-infile") == NULL && cmd_ln_boolean_r(config, "-inmic") == FALSE)) {
E_INFO("Specify '-infile <file.wav>' to recognize from file or '-inmic yes' to recognize from microphone.\n");
cmd_ln_free_r(config);
return 1;
}
ps_default_search_args(config);
ps = ps_init(config);
if (ps == NULL) {
cmd_ln_free_r(config);
return 1;
}
E_INFO("%s COMPILED ON: %s, AT: %s\n\n", argv[0], __DATE__, __TIME__);
if (cmd_ln_str_r(config, "-infile") != NULL) {
recognize_from_file();
} else if (cmd_ln_boolean_r(config, "-inmic")) {
recognize_from_microphone();
}
ps_free(ps);
cmd_ln_free_r(config);
return 0;
}
#if defined(_WIN32_WCE)
#pragma comment(linker,"/entry:mainWCRTStartup")
#include <windows.h>
//Windows Mobile has the Unicode main only
int
wmain(int32 argc, wchar_t * wargv[])
{
char **argv;
size_t wlen;
size_t len;
int i;
argv = malloc(argc * sizeof(char *));
for (i = 0; i < argc; i++) {
wlen = lstrlenW(wargv[i]);
len = wcstombs(NULL, wargv[i], wlen);
argv[i] = malloc(len + 1);
wcstombs(argv[i], wargv[i], wlen);
}
//assuming ASCII parameters
return main(argc, argv);
}
#endif
I can compile it by this command:
g++ -o output continuous.cpp -DMODELDIR=\"`pkg-config --variable=modeldir pocketsphinx`\" `pkg-config --cflags --libs pocketsphinx sphinxbase`
And run it by this command : output -inmic yes .
But I like to convert the code as it has no need to get inmic yes and it automatically starts the program from microphone. But I got segmentation fault(core dumped) error when I changed these parts:
static const arg_t cont_args_def= {"-inmic",
ARG_BOOLEAN,
"no",
"Transcribe audio from microphone."};
int main(int argc, char *argv[])
{
config = cmd_ln_parse_r(NULL, cont_args_def, argc, argv, TRUE);
if (cmd_ln_boolean_r(config, "-inmic")) {
recognize_from_microphone();
}
// recognize_from_microphone();
ps_free(ps);
cmd_ln_free_r(config);
return 0;
}
I searched a lot and red the documentation but couldn't understand what's the problem?
Change the last argument passed to cmd_ln_parse_r from TRUE to FALSE.
It has something to do with strict checking.
I figured this out by reading the source code for cmd_ln.c in the sphinxbase code.
I also changed the boolean value for -inmic in cont_args_def from "no" to "yes".

How to listen continuosly SSDP response after sending M-SEARCH

I would like to search Sat>IP servers on the network. Sat>IP servers advertise their presence to other Sat>IP servers and clients.
I must not continuosly send M-SEARCH messages but that instead it listens to server NOTIFY messages.
After initalizing network settings of my device, I'm sending M-SEARCH message and getting response if there is already any active Sat>IP server.
However, I couldn't get any response, If I opens Sat>IP server after sending M-SEARCH message.
Here's my code.
void SatIP::InitDiscoverThread()
{
if(INVALID_THREAD_CHK == DiscoverThreadChk)
{
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, PTHREAD_STACK_SIZE);
printf("InitDiscoverThread pthread_create\n");
DiscoverThreadChk = PTH_RET_CHK(pthread_create(&DiscoverThreadID, &attr, DiscoverThreadFunc, this));
if(DiscoverThreadChk != 0)
{
ASSERT(0);
}
}
}
void SatIP::FinalizeDiscoverThread()
{
if(INVALID_THREAD_CHK != DiscoverThreadChk)
{
printf("FinalizeDiscoverThread pthread_cancel\n");
pthread_cancel(DiscoverThreadID);
DiscoverThreadChk = INVALID_THREAD_CHK;
close(discoverSocket);
}
}
void *SatIP::DiscoverThreadFunc(void* arg)
{
SatIP* satip = (SatIP *)arg;
satip->ListenSSDPResponse();
pthread_exit(NULL);
}
bool SatIP::SendMSearchMessage()
{
vSatIPServers.clear();
FinalizeDiscoverThread();
const char *searchSatIPDevice = "M-SEARCH * HTTP/1.1\r\n" \
"HOST: 239.255.255.250:1900\r\n" \
"MAN: \"ssdp:discover\"\r\n" \
"MX: 2\r\n" \
"ST: urn:ses-com:device:SatIPServer:1\r\n\r\n";
struct sockaddr_in upnpControl, broadcast_addr;
discoverSocket = socket(AF_INET, SOCK_DGRAM, 0);
if (discoverSocket == INVALID_SOCKET)
{
printf("socked failed INVALID_SOCKET\n");
return false;
}
struct timeval tv;
tv.tv_sec = 1;
tv.tv_usec = 0;
if(setsockopt(discoverSocket, SOL_SOCKET, SO_RCVTIMEO, (char*)&tv, sizeof(tv)) == SOCKET_ERROR)
{
printf("setsockopt timeout failed\n");
close(discoverSocket);
return false;
}
socklen_t ttl = 2;
if(setsockopt(discoverSocket, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) == SOCKET_ERROR)
{
printf("setsockopt TTL failed\n");
close(discoverSocket);
return false;
}
if(setsockopt(discoverSocket, SOL_SOCKET, SO_BROADCAST, searchSatIPDevice, sizeof(searchSatIPDevice)) == SOCKET_ERROR)
{
printf("setsockopt broadcast failed\n");
close(discoverSocket);
return false;
}
upnpControl.sin_family = AF_INET;
upnpControl.sin_port = htons(0);
upnpControl.sin_addr.s_addr = INADDR_ANY;
if (bind(discoverSocket, (sockaddr*)&upnpControl, sizeof(upnpControl)) == SOCKET_ERROR)
{
printf("bind failed\n");
close(discoverSocket);
return false;
}
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_port = htons(1900);
broadcast_addr.sin_addr.s_addr = inet_addr("239.255.255.250");
for(int i = 0; i < 3; i++)
{
if(sendto(discoverSocket, searchSatIPDevice, strlen(searchSatIPDevice), 0, (sockaddr *)&broadcast_addr, sizeof(broadcast_addr)) == SOCKET_ERROR)
{
//printf("sendto failed\n");
close(discoverSocket);
return false;
}
else
{
usleep(10*100);
}
}
InitDiscoverThread();
return true;
}
void SatIP::ListenSSDPResponse()
{
while(1)
{
char buf[512];
memset(buf, 0, 512);
struct sockaddr_in broadcast_addr;
broadcast_addr.sin_family = AF_INET;
broadcast_addr.sin_port = htons(1900);
broadcast_addr.sin_addr.s_addr = inet_addr("239.255.255.250");
int bcLen = sizeof(broadcast_addr);
//bool bRet = false;
while (recvfrom(discoverSocket, buf, 512, 0, (struct sockaddr*)&broadcast_addr, (socklen_t*)&bcLen) > 0)
{
printf("buf:%s\n",buf);
SATIP_SERVER_DESCRIPTION stServerDesc;
ostringstream ss;
if(strstr(buf, "device:SatIPServer"))
{
int i = 0;
char *deviceIp = strstr(buf, "LOCATION:") + 9; // get xml location including server description
while(deviceIp[i] == ' ') i++; // remove spaces from string
while(!isspace(deviceIp[i]))
{
ss << deviceIp[i];
++i;
}
stServerDesc.location = ss.str().c_str();
printf("location:%s\n",stServerDesc.location.c_str());
ss.str(""); // clear ss
i=0; // clear counter
deviceIp = strstr(buf, "http://") + 7; // get ip address
while(deviceIp[i] != ':')
{
ss << deviceIp[i];
++i;
}
stServerDesc.ipAddr = ss.str().c_str();
printf("ipAddr:%s\n", stServerDesc.ipAddr.c_str());
DownloadDeviceDescription(&stServerDesc);
stServerDesc.macAddr = GetMACAddressviaIP(stServerDesc.ipAddr);
printf("macAddr:%s\n", stServerDesc.macAddr.c_str());
if(IsServerProperToAdd(&stServerDesc))
vSatIPServers.push_back(stServerDesc);
printf("\n");
//bRet = true;
}
memset(buf, 0, 512);
}
}
}
How can I fix this issue? Any help would be appreciated.
Listening SSDP notify message is not related to sending M-SEARCH message. Devices like Sat>IP send NOTIFY message to 239.255.255.250 periodically even if you don't send M-SEARCH message. So, you should join a multicast group and receives from the group.
You can use the listener program in the following link by changing HELLO_PORT as 1900 and HELLO_GROUP as "239.255.255.250".
http://ntrg.cs.tcd.ie/undergrad/4ba2/multicast/antony/example.html
/*
* listener.c -- joins a multicast group and echoes all data it receives from
* the group to its stdout...
*
* Antony Courtney, 25/11/94
* Modified by: Frédéric Bastien (25/03/04)
* to compile without warning and work correctly
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <time.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#define HELLO_PORT 1900
#define HELLO_GROUP "239.255.255.250"
#define MSGBUFSIZE 256
main(int argc, char *argv[])
{
struct sockaddr_in addr;
int fd, nbytes,addrlen;
struct ip_mreq mreq;
char msgbuf[MSGBUFSIZE];
u_int yes=1; /*** MODIFICATION TO ORIGINAL */
/* create what looks like an ordinary UDP socket */
if ((fd=socket(AF_INET,SOCK_DGRAM,0)) < 0) {
perror("socket");
exit(1);
}
/**** MODIFICATION TO ORIGINAL */
/* allow multiple sockets to use the same PORT number */
if (setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&yes,sizeof(yes)) < 0) {
perror("Reusing ADDR failed");
exit(1);
}
/*** END OF MODIFICATION TO ORIGINAL */
/* set up destination address */
memset(&addr,0,sizeof(addr));
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=htonl(INADDR_ANY); /* N.B.: differs from sender */
addr.sin_port=htons(HELLO_PORT);
/* bind to receive address */
if (bind(fd,(struct sockaddr *) &addr,sizeof(addr)) < 0) {
perror("bind");
exit(1);
}
/* use setsockopt() to request that the kernel join a multicast group */
mreq.imr_multiaddr.s_addr=inet_addr(HELLO_GROUP);
mreq.imr_interface.s_addr=htonl(INADDR_ANY);
if (setsockopt(fd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq)) < 0) {
perror("setsockopt");
exit(1);
}
/* now just enter a read-print loop */
while (1) {
addrlen=sizeof(addr);
if ((nbytes=recvfrom(fd,msgbuf,MSGBUFSIZE,0,
(struct sockaddr *) &addr,&addrlen)) < 0) {
perror("recvfrom");
exit(1);
}
puts(msgbuf);
}
}

suspicious RCU usage?

I'm running custom Fedora 17 Kernel 3.3.0-0.rc5.git3.1.yfkm2.fc17.x86_64, and the warning was shown on dmesg:
[ 858.634304]
[ 858.634324] ===============================
[ 858.634350] [ INFO: suspicious RCU usage. ]
[ 858.634375] 3.3.0-0.rc5.git3.1.yfkm2.fc17.x86_64 #1 Not tainted
[ 858.634409] -------------------------------
[ 858.634435] kernel/pid.c:425 find_task_by_pid_ns() needs rcu_read_lock() protection!
[ 858.634478]
[ 858.634479] other info that might help us debug this:
[ 858.634480]
[ 858.634528]
[ 858.634529] rcu_scheduler_active = 1, debug_locks = 0
[ 858.634567] no locks held by monitor/10550.
[ 858.634591]
[ 858.634592] stack backtrace:
[ 858.634620] Pid: 10550, comm: monitor Not tainted 3.3.0-0.rc5.git3.1.yfkm2.fc17.x86_64 #1
[ 858.634666] Call Trace:
[ 858.634688] [<ffffffff810c8c55>] lockdep_rcu_suspicious+0xe5/0x100
[ 858.634727] [<ffffffff81086921>] find_task_by_pid_ns+0x81/0xa0
[ 858.634762] [<ffffffff81086962>] find_task_by_vpid+0x22/0x30
[ 858.634798] [<ffffffff8131ccd5>] yfkm2_is_pid_running+0x15/0x40
[ 858.634835] [<ffffffff8131ce54>] sys_yfkm2_monitor+0x14/0x80
[ 858.634870] [<ffffffff816a6ba9>] system_call_fastpath+0x16/0x1b
monitor is user application that call sys_yfkm2_monitor syscall passing a pid to it. The custom code worked as expected but I'm curious with the warning message shown on dmesg. What am I doing wrong?
The user application monitor.c:
#include <stdio.h>
#include <unistd.h>
#include <sys/syscall.h>
#define SYS_yfkm2_monitor __NR_yfkm2_monitor
#define SYS_yfkm2_notifyme __NR_yfkm2_notifyme
int main (int argc, char *argv[])
{
if (argc < 2) {
printf("Error. Use %s <PID>\n", argv[0]);
return 1;
}
pid_t pid = atoi(argv[1]);
long ret;
ret = syscall(SYS_yfkm2_monitor, pid);
if (ret == 0){
printf("Sucess on adding %d!\n", pid);
return 0;
} else {
printf("Failure! Is %s a valid PID?\n", argv[1]);
return 1;
}
}
The Kernel code:
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/kthread.h>
#define YFKM2_KT_TIMEOUT (1*HZ) /* 1 second */
struct yfkm2 {
pid_t monitor; /* PID to monitor */
pid_t notifyme; /* PID to notify */
struct list_head list; /* Linked List struct */
};
/* How many Kernel Threads are running? */
atomic_t yfkm2_kthread_run_count = ATOMIC_INIT(0);
/* Define and initialize yfkm2_(linked)list */
LIST_HEAD(yfkm2_list);
/* Define and initialize yfkm2_(read&write)lock */
DEFINE_RWLOCK(yfkm2_lock);
/*
* yfkm2_is_pid_running(pid_t pid)
*
* Check if pid is running
*
* return 0 if pid is running
* return 1 if pid is not running
*/
int yfkm2_is_pid_running(pid_t pid)
{
struct task_struct *q;
q = find_task_by_vpid(pid);
if (q != NULL && q->pid == pid)
return 0;
return 1;
}
/*
* yfkm2_kill(pid_t pid)
*
* Kills pid
*
* return 0 if pid was running and send SIGKILL to pid
* return 1 if pid is not running
*/
int yfkm2_kill(pid_t pid)
{
struct task_struct *q;
q = find_task_by_vpid(pid);
if (q != NULL) {
force_sig(SIGKILL, q);
return 0;
}
return 1;
}
/*
* int yfkm2_kthread(void *data)
*
* The Kernel Thread
*
* Traverse the yfkm2_list looking for yfkm2->notifyme that are not 0.
* If any found, check if correspondent yfkm2->monitor is still running. If not
* kill yfkm2->notifyme. After traversing the list, check if the list is empty.
* If so return 0. If not sleep one second and start again.
*
* return 0 if yfkm2_list is empty
* should never return 1
*/
int yfkm2_kthread(void *data) /* data is NEVER used */
{
struct yfkm2 *yfkm2_tmp, *yfkm2_tmp2;
bool empty;
while (true) {
/* Needs write protection due possible item removal from list */
write_lock(&yfkm2_lock); /* Write lock */
list_for_each_entry_safe(yfkm2_tmp, yfkm2_tmp2,
&yfkm2_list, list) {
if (yfkm2_tmp->notifyme != 0) {
if (yfkm2_is_pid_running(yfkm2_tmp->monitor) != 0) {
yfkm2_kill(yfkm2_tmp->notifyme);
list_del(&yfkm2_tmp->list);
kfree(yfkm2_tmp);
}
}
}
write_unlock(&yfkm2_lock); /* Write unlock */
read_lock(&yfkm2_lock); /* Read lock */
empty = list_empty(&yfkm2_list);
read_unlock(&yfkm2_lock); /* Read unlock */
if (empty) {
/* The counter is increased at sys_yfkm2_notifyme()
* Before exit, decrease atomic run counter */
atomic_dec(&yfkm2_kthread_run_count);
return 0;
}
set_current_state(TASK_INTERRUPTIBLE);
schedule_timeout(YFKM2_KT_TIMEOUT);
}
/* Before exit, decrease atomic run counter */
atomic_dec(&yfkm2_kthread_run_count);
return 1;
}
/*
* asmlinkage long sys_yfkm2_monitor(pid_t monitor)
*
* The system call that check if monitor correspond to a running pid and stores
* monitor at yfkm2_list->monitor
*
* return 0 if pid is running
* return 1 if pid is not running
*/
asmlinkage long sys_yfkm2_monitor(pid_t monitor)
{
struct yfkm2 *yfkm2_tmp;
if (yfkm2_is_pid_running(monitor) == 0) {
yfkm2_tmp = kmalloc(sizeof(*yfkm2_tmp), GFP_KERNEL);
yfkm2_tmp->monitor = monitor;
yfkm2_tmp->notifyme = 0;
write_lock(&yfkm2_lock);
list_add(&yfkm2_tmp->list, &yfkm2_list);
write_unlock(&yfkm2_lock);
return 0;
}
return 1;
}
/*
* asmlinkage long sys_yfkm2_notifyme(pid_t monitor, pid_t notifyme)
*
* The system call that looks for monitor at yfkm2_list->monitor. If found
* store notifyme at yfkm2_list->notifyme. It also starts the kernel thread
* if it is not running.
*
* return 0 if pid is running
* return 1 if pid is not running
*/
asmlinkage long sys_yfkm2_notifyme(pid_t monitor, pid_t notifyme)
{
struct yfkm2 *yfkm2_tmp;
bool found_monitored_pid = false;
write_lock(&yfkm2_lock); /* Write lock */
list_for_each_entry(yfkm2_tmp, &yfkm2_list, list) {
if (yfkm2_tmp->monitor == monitor) {
yfkm2_tmp->notifyme = notifyme;
found_monitored_pid = true;
break;
}
}
write_unlock(&yfkm2_lock); /* Write unlock */
if (found_monitored_pid) {
if (atomic_read(&yfkm2_kthread_run_count) < 1) {
/* The counter is decreased at yfkm2_kthread()
* Before start, increase atomic run counter */
atomic_inc(&yfkm2_kthread_run_count);
kthread_run(&yfkm2_kthread, NULL, "yfkm2_kthread");
}
return 0;
} else {
return 1;
}
}
You are not performing correct locking on the task list. For example, your yfkm2_kill() function should be:
int yfkm2_kill(pid_t pid)
{
struct task_struct *q;
rcu_read_lock();
q = find_task_by_vpid(pid);
if (q)
get_task_struct(q);
rcu_read_unlock();
if (q == NULL)
return 1;
force_sig(SIGKILL, q);
put_task_struct(q);
return 0;
}
...but your whole design appears to be severely racy. For example, one of the ->monitor tasks could exit and be replaced with a new, different task with the same PID before your kernel thread notices.
You seem to be running code without the required locks.
Such things tend to work, except that they crash once in a while (possibly a long while).
I don't know these functions so much, but it seems like find_task_by_vpid should be called under some RCU lock (probably the one that protects the process list), in read mode.

USB applications using libusb library

I want to use libusb library for writing some test applications for USB.
Can any one please suggest how to set control transfers using usb_control_msg call?
I am getting bad descriptor error while running the following code.
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "usb.h"
static int vendor_id;
static int product_id;
typedef struct{
int requesttype;
int request;
int value;
int index;
char *bytes;
int size;
int timeout;
}ctrlmsg_param;
void print_endpoint(struct usb_endpoint_descriptor *endpoint)
{
printf("=====End point Information====\n");
printf("bEndpointAddress: %x\n", endpoint->bEndpointAddress);
printf("bmAttributes: %x\n", endpoint->bmAttributes);
printf("wMaxPacketSize: %d\n", endpoint->wMaxPacketSize);
printf("bInterval: %d\n", endpoint->bInterval);
printf("bRefresh: %d\n", endpoint->bRefresh);
printf("bSynchAddress: %d\n", endpoint->bSynchAddress);
}
void print_altsetting(struct usb_interface_descriptor *interface)
{
int i;
printf("\n=====Alternate Setting Information====\n");
printf("bInterfaceNumber: %d\n", interface->bInterfaceNumber);
printf("bAlternateSetting: %d\n", interface->bAlternateSetting);
printf("bNumEndpoints: %d\n", interface->bNumEndpoints);
printf("bInterfaceClass: %d\n", interface->bInterfaceClass);
printf("bInterfaceSubClass: %d\n", interface->bInterfaceSubClass);
printf("bInterfaceProtocol: %d\n", interface->bInterfaceProtocol);
printf("iInterface: %d\n", interface->iInterface);
for (i = 0; i < interface->bNumEndpoints; i++)
print_endpoint(&interface->endpoint[i]);
}
void print_interface(struct usb_interface *interface)
{
int i;
for (i = 0; i < interface->num_altsetting; i++)
print_altsetting(&interface->altsetting[i]);
}
void print_configuration(struct usb_config_descriptor *config)
{
int i;
printf("=====Configuration Information====\n");
printf("wTotalLength: %d\n", config->wTotalLength);
printf("bNumInterfaces: %d\n", config->bNumInterfaces);
printf("bConfigurationValue: %d\n", config->bConfigurationValue);
printf("iConfiguration: %d\n", config->iConfiguration);
printf("bmAttributes: %x\n", config->bmAttributes);
printf("MaxPower: %d\n", config->MaxPower);
for (i = 0; i < config->bNumInterfaces; i++)
print_interface(&config->interface[i]);
}
int print_device(struct usb_device *dev)
{
usb_dev_handle *udev;
char str[100];
int ret, i;
udev = usb_open(dev);
if (udev) {
if (dev->descriptor.iManufacturer) {
ret = usb_get_string_simple(udev, dev->descriptor.iManufacturer, str, sizeof(str));
if (ret > 0)
{
printf("Manufacturer is %s\n",str);
}
}
if (dev->descriptor.iProduct) {
ret = usb_get_string_simple(udev, dev->descriptor.iProduct, str, sizeof(str));
if (ret > 0)
{
printf("Product is %s\n",str);
}
}
}
if (udev)
usb_close(udev);
printf("Possible configurations are %x\n",dev->descriptor.bNumConfigurations);
sleep(2);
for (i = 0; i < dev->descriptor.bNumConfigurations; i++)
print_configuration(&dev->config[i]);
return 0;
}
int htod( const char* str )
{
int decimal;
sscanf( str, "%x", &decimal);
return decimal;
}
void set_data(struct usb_device *dev)
{
ctrlmsg_param param;
param.requesttype= 0;
param.request=0;
param.value=0;
param.index=0;
param.bytes=10;
param.size=0;
param.timeout=5000;
usb_control_msg(dev, param.requesttype, param.request, param.value, param.index, param.bytes, param.size, param.timeout);
printf("error is %s\n",strerror(errno));
return;
}
int main(int argc, char *argv[])
{
struct usb_bus *bus;
struct usb_device *dev;
if(argc != 3)
{
printf("Error in number of arguments\n");
printf("Usage:./usb_info <vendor id> <product id>\n");
exit(0);
}
vendor_id=htod(argv[1]);
product_id=htod(argv[2]);
printf("initializing USB library\n");
usb_init();
printf("Finding Buses and Devices\n");
usb_find_busses();
usb_find_devices();
for (bus = usb_get_busses(); bus; bus = bus->next) {
for (dev = bus->devices; dev; dev = dev->next) {
if ((dev->descriptor.idProduct == product_id) && (dev->descriptor.idVendor == vendor_id)){
printf("Found device with produxt id %x and vendor id %x\n",product_id,vendor_id);
print_device(dev);
set_data(dev);
print_device(dev);
}
}
}
return 0;
}
Regards,
Sandeep
I think that you mean usb_control_msg() is returns an error code for "bad descriptor". Please clarify if this is incorrect.
USB control transfers have some very specific formatting rules, and if the packet you are forming is sent to any compliant device, it will return a request error / stall on the bus.
You are sending the control transfer:
bmRequestType = 0x00
bRequest = 0x00
wValue = 0x0000
wIndex = 0x0000
wSize = 0x0000
this should be interpreted by the USB device as a GET_STATUS request, so wLength is required to be 2, and bmRequestType needs to have the top bit set, indicating this is an IN direction request (from the host's point of view). This is all from Chapter 9 of the USB specification 1.1/2.0/3.1 available at www.usb.org.
The parameter char *bytes (your param.bytes) also needs to be an address/pointer in the call you are making.
A good standard control transfer to test with would be:
bmRequestType = 0x80
bRequest = 0x06
wValue = 0x0001
wIndex = 0x0000
wSize = 0x0008
This request will return the first 8 bytes of the Device Descriptor, it is valid for every USB device, in all states.
The other transfer types (bulk, interrupt) don't have these strict formatting rules, and can be an easier place to start. I'd imagine you have already moved past this issue, since the question has been posted for quite a while, but maybe this response will still help someone else.

True non-blocking two-way communication between parent and external child process

I have read around 50 posts and tutorials on this topic, I have copied, written and tested around 20 alternatives and done every possible research I can think of. Still, I have not seen a working solution for the following problem:
Parent process A wants to pass data to an external process B, let process B modify the data and pass it back to parent process A, then continue with parent process A. Process B is part of an external program suite that I have no influence over, and that is normally run like this on the UNIX command line:
< input_data program_B1 | program_B2 | program_B3 > output_data
...where
input_data, output_data: Some data that is processed in programs B1-B3
program_B1,B2,B3: Programs that read data from stdin (fread) and output to stdout (fwrite) and apply some processing to the data.
So, in sequence:
(1) Parent process A passes data to child process B
(2) Child process B reads data and modifies it
(3) Child process B passes data back to parent process A
(4) Parent process A reads data and continues (for example passing it further on to a process B2..).
(5) Parent process A passes another data set to child process B etc.
The problem is, whatever I do, the program almost always ends up hanging on a read/fread (or write/fwrite?) to or from a pipe.
One important thing to note is that the parent process cannot simply close the pipes after passing data on to the child process, because it works in a loop and wants to pass another set of data to the child process once it has finished processing the first set.
Here is a working set of parent/child programs (compile with g++ pipe_parent.cc -o pipe_parent, g++ pipe_child.cc -o pipe_child) illustrating the problem with unnamed pipes. I have also tried named pipes, but not as extensively. Each execution can have a slightly different outcome. If the sleep statement is omitted in the parent, or the fflush() statement is omitted in the child, the pipes will almost surely block. If the amount of data to be passed on is increased, it will always block independent of the sleep or fflush.
Parent program A:
#include <cstring>
#include <cstdio>
#include <cstdlib>
extern "C" {
#include <unistd.h>
#include <fcntl.h>
}
using namespace std;
/*
* Parent-child inter-communication
* Child is external process
*/
int main() {
int fd[2];
if( pipe(fd) == -1 ) {
fprintf(stderr,"Unable to create pipe\n");
}
int fd_parentWrite = fd[1];
int fd_childRead = fd[0];
if( pipe(fd) == -1 ) {
fprintf(stderr,"Unable to create pipe\n");
exit(-1);
}
int fd_childWrite = fd[1];
int fd_parentRead = fd[0];
pid_t pid = fork();
if( pid == -1 ) {
fprintf(stderr,"Unable to fork new process\n");
exit(-1);
}
if( pid == 0 ) { // Child process
dup2( fd_childRead, fileno(stdin) ); // Redirect standard input(0) to child 'read pipe'
dup2( fd_childWrite, fileno(stdout) ); // Redirect standard output(1) to child 'write pipe'
close(fd_parentRead);
close(fd_parentWrite);
close(fd_childRead);
close(fd_childWrite);
// execl replaces child process with an external one
int ret = execl("/disk/sources/pipe_test/pipe_child","pipe_child",NULL);
fprintf(stderr,"External process failed, return code: %d...\n", ret);
exit(-1);
// Child process is done. Will not continue from here on
}
else { // Parent process
// Nothing to set up
}
// ...more code...
if( pid > 0 ) { // Parent process (redundant if statement)
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
for( int i = 0; i < numElements; i++ ) {
buffer[i] = (float)i;
}
for( int iter = 0; iter < 5; iter++ ) {
fprintf(stderr,"--------- Iteration #%d -----------\n", iter);
int sizeWrite = (int)write( fd_parentWrite, buffer, totalSize );
if( sizeWrite == -1 ) {
fprintf(stderr,"Parent process write error\n");
exit(-1);
}
fprintf(stderr,"Parent #%d: Wrote %d elements. Total size: %d\n", iter, sizeWrite, totalSize);
sleep(1); // <--- CHANGE!
int sizeRead = (int)read( fd_parentRead, buffer, totalSize );
if( sizeRead <= 0 ) {
fprintf(stderr,"Parent process read error\n");
}
while( sizeRead < totalSize ) {
fprintf(stderr,"Parent #%d: Read %d elements, continue reading...\n", iter, sizeRead);
int sizeNew = (int)read( fd_parentRead, &buffer[sizeRead], totalSize-sizeRead );
fprintf(stderr," ...newly read %d elements\n", sizeNew);
if( sizeNew < 0 ) {
exit(-1);
}
sizeRead += sizeNew;
}
fprintf(stderr,"Parent #%d: Read %d elements. Total size: %d\n", iter, sizeRead, totalSize);
fprintf(stderr,"Examples : %f %f %f\n", buffer[0], buffer[10], buffer[100]);
}
delete [] buffer;
}
close(fd_parentRead);
close(fd_parentWrite);
close(fd_childRead);
close(fd_childWrite);
return 0;
}
Child program B:
#include <cstdio>
using namespace std;
int main() {
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
int counter = 0;
int sizeRead = 0;
do {
sizeRead = fread( buffer, 1, totalSize, stdin);
fprintf(stderr,"Child #%d: Read %d elements, buffer100: %f\n", counter, sizeRead, buffer[100]);
if( sizeRead > 0 ) {
for( int i = 0; i < numElements; i++ ) {
buffer[i] += numElements;
}
int sizeWrite = fwrite( buffer, 1, totalSize, stdout);
fflush(stdout); // <--- CHANGE!
fprintf(stderr,"Child #%d: Wrote %d elements\n", counter, sizeWrite);
counter += 1;
}
} while( sizeRead > 0 );
return 0;
}
Is there any way to check when the pipe has enough data to be read? Or is there an alternative way to resolve the above problem, with or without pipes?
Please help!
Possibly the best solution when reading is to check with select whether you can read from the pipe. You can even pass a timeout. The alternative might be setting the O_NONBLOCK flag on file descriptor 0 (stdin) with fcntl, though I think the select way is better.
As with ensuring non-blocking write: that's a bit harder as you don't know how much you can write before the pipe blocks. One way (that I feel is very ugly) would be to only write 1 byte chunks and again check with select whether you can write. But that would be a performance killer, so use only if performance in communication is not an issue.
The first answer (using select to find out whether a pipe is ready to be read from) was good but didn't really solve my issue, see also my previous comments. Sooner or later I always ended up with a "race condition" where the program kept hanging either on a read or write.
The solution (maybe not be the only one?) is to run the child-to-parent data transfer in a different thread. I also went back and implemented the pipes as named pipes. It would probably also work with unnamed pipes but I didn't check that.
The final code is below. Note that no explicit flushing is required; the parent-to-child and child-to-parent data transfers are now decoupled. Any comments how this can be improved welcome! One residual problem I can see is that the pipes may fill up depending on how long time the child needs to process the data. I'm not sure how likely this is to happen. And by the way this worked fine with my external programs, not only with the provided child program.
Parent program A:
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <string>
#include <iostream>
extern "C" {
#include <unistd.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <errno.h>
#include <signal.h>
#include <sys/wait.h>
#include <pthread.h>
}
using namespace std;
static int const READING = -1;
static int const BUFFER_READY = 1;
static int const FINISHED = 0;
/*
* Parent-child inter-communication
* Child is external process
*/
struct threadStruct {
FILE* file_c2p;
int sizeBuffer;
float* buffer;
int io_flag;
};
// Custom sleep function
void mini_sleep( int millisec ) {
struct timespec req={0},rem={0};
time_t sec = (int)(millisec/1000);
millisec = (int)(millisec-(sec*1000));
req.tv_sec = sec;
req.tv_nsec = millisec*1000000L;
nanosleep(&req,&rem);
}
// Function to be executed within separate thread: Reads in data from file pointer
// Hand-shaking with main thread is done via the flag 'io_flag'
void *threadFunction( void *arg ) {
threadStruct* ptr = (threadStruct*)arg;
ptr->io_flag = READING;
while( ptr->io_flag != FINISHED ) {
if( ptr->io_flag == READING ) {
int sizeRead = fread( ptr->buffer, 1, ptr->sizeBuffer, ptr->file_c2p );
if( sizeRead <= 0 ) {
ptr->io_flag = FINISHED;
return NULL;
}
ptr->io_flag = BUFFER_READY;
}
else {
mini_sleep(10);
}
}
return NULL;
}
//--------------------------------------------------
int main() {
std::string filename_p2c("/tmp/fifo11_p2c");
std::string filename_c2p("/tmp/fifo11_c2p");
fprintf(stderr,"..started\n");
int status = mknod(filename_p2c.c_str(), S_IRUSR | S_IWUSR | S_IFIFO, 0);
if( (status == -1) && (errno != EEXIST) ) {
fprintf(stderr,"Error creating named pipe: %s\n", strerror(errno));
exit(-1);
}
status = mknod(filename_c2p.c_str(), S_IRUSR | S_IWUSR | S_IFIFO, 0);
if( (status == -1) && (errno != EEXIST) ) {
fprintf(stderr,"Error creating named pipe: %s\n", strerror(errno));
exit(-1);
}
FILE* file_dump = fopen("parent_dump","w");
int fd_p2c;
int fd_c2p;
FILE* file_c2p = NULL;
//--------------------------------------------------
// Set up parent/child processes
//
pid_t pid = fork();
if( pid == -1 ) {
fprintf(stderr,"Unable to fork new process\n");
}
if( pid == 0 ) { // Child process
fd_p2c = open( filename_p2c.c_str(), O_RDONLY );
if( fd_p2c < 0 ) {
fprintf(stderr,"Child: Error opening the named pipe: %d %d '%s'\n", fd_p2c, errno, strerror(errno));
exit(-1);
}
fd_c2p = open( filename_c2p.c_str(), O_WRONLY );
if( fd_c2p < 0 ) {
fprintf(stderr,"Child: Error opening the named pipe: %d %d '%s'\n", fd_c2p, errno, strerror(errno));
exit(-1);
}
dup2(fd_p2c,fileno(stdin)); // Redirect standard input(0) to child 'read pipe'
dup2(fd_c2p,fileno(stdout)); // Redirect standard output(1) to child 'write pipe'
close(fd_p2c);
close(fd_c2p);
int ret = execl("/disk/sources/pipe_test/pipe_child","pipe_child",NULL);
fprintf(stderr,"External process failed, return code: %d...\n", ret);
kill( getppid(), 9 ); // Kill parent process
exit(-1);
}
else { // Parent process
fd_p2c = open( filename_p2c.c_str(), O_WRONLY );
if( fd_p2c < 0 ) {
fprintf(stderr,"Parent: Error opening the named pipe: %d %d '%s'\n", fd_p2c, errno, strerror(errno));
exit(-1);
}
file_c2p = fopen( filename_c2p.c_str(), "r");
fd_c2p = fileno( file_c2p );
if( fd_c2p < 0 ) {
fprintf(stderr,"Parent: Error opening the named pipe: %d %d '%s'\n", fd_c2p, errno, strerror(errno));
exit(-1);
}
}
int numElements = 10000;
int sizeBuffer = numElements * sizeof(float);
float* bufferIn = new float[numElements];
float* bufferOut = new float[numElements];
for( int i = 0; i < numElements; i++ ) {
bufferIn[i] = 0.0;
}
int numIterations = 5;
int numBytesAll = numElements * sizeof(float) * numIterations;
pthread_t thread;
threadStruct* threadParam = new threadStruct();
threadParam->file_c2p = file_c2p;
threadParam->sizeBuffer = sizeBuffer;
threadParam->buffer = bufferIn;
threadParam->io_flag = READING;
int thread_stat = pthread_create( &thread, NULL, threadFunction, threadParam );
if( thread_stat < 0 ) {
fprintf(stderr,"Error when creating thread\n");
exit(-1);
}
int readCounter = 0;
int numBytesWrite = 0;
int numBytesRead = 0;
for( int iter = 0; iter < numIterations; iter++ ) {
for( int i = 0; i < numElements; i++ ) {
bufferOut[i] = (float)i + iter*numElements*10;
}
int sizeWrite = (int)write( fd_p2c, bufferOut, sizeBuffer );
if( sizeWrite == -1 ) {
fprintf(stderr,"Parent process write error\n");
exit(-1);
}
numBytesWrite += sizeWrite;
fprintf(file_dump,"Parent #%d: Wrote %d/%d bytes.\n", iter, numBytesWrite, numBytesAll);
if( iter == numIterations-1 ) close(fd_p2c); // Closing output pipe makes sure child receives EOF
if( threadParam->io_flag != READING ) {
numBytesRead += sizeBuffer;
fprintf(file_dump,"Parent #%d: Read %d/%d bytes. Examples: %f %f\n",
readCounter, numBytesRead, numBytesAll, bufferIn[1], bufferIn[numElements-1] );
readCounter += 1;
if( threadParam->io_flag != FINISHED ) threadParam->io_flag = READING;
}
}
//********************************************************************************
//
fprintf(file_dump,"------------------------------\n");
while( threadParam->io_flag != FINISHED ) {
if( threadParam->io_flag == BUFFER_READY ) {
numBytesRead += sizeBuffer;
fprintf(file_dump,"Parent #%d: Read %d/%d bytes. Examples: %f %f\n",
readCounter, numBytesRead, numBytesAll, bufferIn[1], bufferIn[numElements-1] );
readCounter += 1;
if( threadParam->io_flag != FINISHED ) threadParam->io_flag = READING;
}
else {
mini_sleep(10);
}
}
// wait for thread to finish before continuing
pthread_join( thread, NULL );
fclose(file_dump);
fclose(file_c2p);
waitpid(pid, &status, 0); // clean up any children
fprintf(stderr,"..finished\n");
delete [] bufferIn;
delete [] bufferOut;
return 0;
}
Child program B:
#include <cstdio>
using namespace std;
int main() {
int numElements = 10000;
int totalSize = numElements * sizeof(float);
float* buffer = new float[numElements];
FILE* file_dump = fopen("child_dump","w");
int counter = 0;
int sizeRead = 0;
do {
sizeRead = fread( buffer, 1, totalSize, stdin);
if( sizeRead > 0 ) {
fprintf(file_dump,"Child #%d: Read %d bytes, examples: %f %f\n", counter, sizeRead, buffer[1], buffer[numElements-1]);
for( int i = 0; i < numElements; i++ ) {
buffer[i] += numElements;
}
int sizeWrite = fwrite( buffer, 1, totalSize, stdout);
fprintf(file_dump,"Child #%d: Wrote %d bytes, examples: %f %f\n", counter, sizeRead, buffer[1], buffer[numElements-1]);
counter += 1;
}
} while( sizeRead > 0 );
fprintf(file_dump,"Child is finished\n");
fclose(file_dump);
fclose(stdout);
return 0;
}