c++ pipe buffering disable - c++

How to disable buffering in pipe. I'm creating a simple recorder/player for I/O. To do this I need record output witch time delays.
To record delays, I need something like this
example tekst
"wait 1s"
example tekst
"wait 1s"
example tekst
...
but if I use
pipe2(in, O_DIRECT );
i see something like this
"wait 100s"
"100 times" example tekst
"wait 100s"
"100 times" example tekst
...
man7 tells:
O_DIRECT (since Linux 3.4)
Create a pipe that performs I/O in "packet" mode. Each
write(2) to the pipe is dealt with as a separate packet, and
read(2)s from the pipe will read one packet at a time.
I tried to disable buffering, by:
fcntl(in[1], F_SETPIPE_SZ, 1);
but it's still not working.
read.cpp
#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <unistd.h>
#include <signal.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <poll.h>
#include <assert.h>
bool keep = true;
void intHandler(int dummy) {
keep = 0;
}
int main(void) {
signal(SIGINT, intHandler);
int in[2];
int out[2];
int pid;
int fo;
char buf[1024];
pipe2(in, O_DIRECT );
pipe2(out, O_DIRECT );
pid = fork();
if (pid == -1) {
perror("fork");
exit(1);
}
if (pid == 0) {
close(in[0]);
close(out[1]);
close(0);
close(1);
dup2(in[1], 1);
dup2(out[0], 0);
close(in[1]);
close(out[0]);
sleep(1);
char *newargv[] = {"/root/Pulpit/a1", NULL, NULL, NULL};
char *newenviron[] = {NULL};
int ret = execve("/root/Pulpit/a1", newargv, newenviron);
printf("%d", ret);
return 0;
} else {
close(out[0]);
close(in[1]);
int n = 0;
while (keep) {
int wyn = read(in[0], buf, 1024);
if (wyn > 0) {
char aa[1024];
write(1, buf, wyn);
fsync(1);
}
}
}
return (0);
}
a1.cpp
#include <cstdlib>
#include <unistd.h>
#include "stdio.h"
using namespace std;
/*
*
*/
int main(int argc, char** argv) {
while(true){
printf("example text\n");
usleep(100000);
}
return 0;
}

Related

Endless request for input when calling open()

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <iostream>
#include <string.h>
int main(){
int fd;
size_t size;
char name[]="aaa.fifо";
umask(0) ;
if (mknod(name, S_IFIFO | 0666, 0) < 0){
printf("Can\'t create FIFO\n");
_exit(-1);
}
if ((fd = open(name, O_WRONLY)) < 0){
printf("Can\'t open FIFO for writing\n");
_exit(-1);
}
char message[60];
while(true){
message[0] = 0;
std::cin.clear();
std::cin >> message;
if(!strcmp(message,"exit"))
{
printf("Exit to programm\n");
break;
}
size = write(fd, message, 60);
if (size < strlen(message)) {
printf("Can\'t write all string to FIFO\n");
_exit(-1);
}
}
close(fd);
return 0;
}
By typing, I realized that the problem arises when calling open ().
When I remove the loop the same trouble Even if cout at the beginning of main write nothing works, but when you remove the lines from open () everything works as it should
I realized that the problem arises when calling open ().
Some process must open the FIFO for reading, then your open() continues.

unshare user namespace, fork, map uid then execvp failing

I am trying to do the following sequence of actions:
unshare the user namespace;
Map the user in child process to root;
execvp.
However, when running id, my code outputs the user as a nobody or fails without error.
#include <sched.h>
#include <cstdio>
#include <cstring>
#include <cerrno>
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include <system_error>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdio.h>
void unshare_user_namespace() {
if (0 != unshare(CLONE_NEWUSER)) {
fprintf(stderr, "%s\n", "USER unshare has failed");
exit(1);
}
}
void map_id() {
int pid = getpid();
char file[100];
if (0 > sprintf(file, "/proc/%d/uid_map", pid)) {
printf("Couldn't sprintf uid_map path.");
exit(1);
}
int fd;
fd = open(file, 1);
if (fd < 0) {
printf("Coudln't open file for writing.\n");
exit(1);
}
int uid = getuid();
char * buf;
if (0 > sprintf(buf, "0 %d 1", uid)) {
printf("Couldn't sprintf uid_map content.");
exit(1);
}
if (write(fd, buf, strlen(buf))) {
printf("Coudln't write mapping into file.\n");
exit(1);
}
free(buf);
close(fd);
}
void start(char * command, char ** args) {
unshare_user_namespace();
int fork_pid = fork();
if (-1 == fork_pid) {
fprintf(stderr, "%s\n", "couldn't fork");
exit(1);
}
if (0 == fork_pid) {
map_id();
if (-1 == execvp(command, args)) {
fprintf(stderr, "%s\n", "couldn't execvp");
exit(1);
}
}
}
int main(int argc, char ** argv) {
start(argv[1], & argv[1]);
int status;
wait( & status);
return 0;
}
I tried reading the man pages for namespaces, unshare etc but couldn't figure out what's wrong with my code.
To run the code:
$ g++ <file_containing_code> && ./a.out id
Pretty sure you've already found the answer, but this is a minimal sample I could come up with:
// gcc -Wall -std=c11
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
#include <sched.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdarg.h>
void write_to_file(const char *which, const char *format, ...) {
FILE * fu = fopen(which, "w");
va_list args;
va_start(args, format);
if (vfprintf(fu, format, args) < 0) {
perror("cannot write");
exit(1);
}
fclose(fu);
}
int main(int argc, char ** argv) {
// array of strings, terminated with NULL entry
char **cmd_and_args = (char**) calloc(argc, sizeof(char*));
for (int i = 1 ; i < argc; i++) {
cmd_and_args[i-1] = argv[i];
}
uid_t uid = getuid();
gid_t gid = getgid();
// first unshare
if (0 != unshare(CLONE_NEWUSER)) {
fprintf(stderr, "%s\n", "USER unshare has failed");
exit(1);
}
// remap uid
write_to_file("/proc/self/uid_map", "0 %d 1", uid);
// deny setgroups (see user_namespaces(7))
write_to_file("/proc/self/setgroups", "deny");
// remap gid
write_to_file("/proc/self/gid_map", "0 %d 1", gid);
// exec the command
if (execvp(cmd_and_args[0], cmd_and_args) < 0) {
perror("cannot execvp");
exit(1);
}
// unreachable
free(cmd_and_args);
return 0;
}

Valgrind with signal handling

In this code, I am trying to ipc with signals. Parent process will send SIGUSR1 signal to his children and waits for a SIGUSR1 signal for conformation of the signal arrive at the child end.
So I have;
Parent --> SIGUSR1 --> CHILD[i]
Parent <--- SIGUSR1 <--- CHILD[i]
this kind of communication between parent child processes. In normal executing, I have never face with a deadlock scenario. But when I run with valgrind, sometimes child process canot receive SIGUSR1 signal from parent process, which is start signal for communication.
Is the valgrind uses some mechanisms to avoid signal communication between processes ?
Parent process :
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#define CHILD_SIZE 80
sigset_t sigusr_mask;
pid_t children[CHILD_SIZE];
void SIGUSR1_handler(int sig)
{
write(1,"test.\n",6);
}
void init_signal()
{
sigset_t blck_msk;
sigemptyset(&blck_msk);
sigaddset(&blck_msk, SIGUSR1);
sigfillset(&sigusr_mask);
sigdelset(&sigusr_mask, SIGUSR1);
struct sigaction usr1_act;
memset(&usr1_act, 0, sizeof(usr1_act));
usr1_act.sa_handler = &SIGUSR1_handler;
sigaction(SIGUSR1, &usr1_act, NULL);
if(-1== sigprocmask(SIG_BLOCK, &blck_msk,NULL))
exit(-1);
}
void create_children(const char* processPath, int round_)
{
for(int i = 0; i < CHILD_SIZE; ++i)
{
pid_t pid_c = fork();
if(pid_c > 0) {
children[i] = pid_c;
}
else if(pid_c == 0)
{
char* arg[1024] = {"childProcess", (char*)0};
execve(processPath, arg, NULL);
}
}
}
// for the synchronization
void wait_childs()
{
for (int i = 0; i < CHILD_SIZE; ++i)
{
// send SIGUSR1 to the children.
kill(children[i], SIGUSR1);
printf("%d : %s\n", children[i],strerror(errno));
// wait until children reply by SIGUSR1
sigsuspend(&sigusr_mask);
}
}
int main(int argc, char const *argv[])
{
init_signal();
create_children("childProcess", 1);
wait_childs();
return (0);
}
Child process :
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <errno.h>
#include "utils.h"
sigset_t sigusr_mask;
void SIGUSR1_handler(int sig) {
write(1,"usr1\n",4);
}
void init_signal()
{
sigfillset(&sigusr_mask);
sigdelset(&sigusr_mask, SIGUSR1);
struct sigaction usr1_act;
memset(&usr1_act, 0, sizeof(usr1_act));
usr1_act.sa_handler = &SIGUSR1_handler;
sigaction(SIGUSR1, &usr1_act, NULL);
}
int main(int argc, char const *argv[])
{
init_signal();
printf("child %d waiting \n",getpid());
// wait until parent starts the communication.
sigsuspend(&sigusr_mask);
// after parent sends SIGUSR1, send reply.
kill(getppid(), SIGUSR1);
return 0;
}

C++ - msgsnd & msgrcv communication between 2 different programs

I have two programs and I want them to communicate together by msgrcv() && msgsnd(). I so have a master program which init the message queue and start the 2 others programs:
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
int main() {
int qid = msgget(ftok(".",'u'), 0);
char* params[3];
params[1] = (char *)malloc(sizeof(char) * 9);
sprintf(params[1], "%d", qid);
params[2] = NULL;
printf("qid = %d and qid(str) = %s", qid, params[1]);
// return (0);
//spawning two child processes
pid_t cpid = fork();
if (cpid == 0) {
params[0] = (char*)"./sender";
execv(params[0], params);
exit(0);
}
cpid = fork();
if (cpid == 0) {
params[0] = (char*)"./receiver";
execv(params[0], params);
exit(0);
}
while (wait(NULL) != -1); // waiting for both children to terminate
msgctl(qid, IPC_RMID, NULL);
std::cout << "parent proc: " << getpid()
<< " now exits" << std::endl;
exit(0);
}
I also prepare the parameters and start the both following programs:
sender
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
int main(int ac, char **av) {
if (ac != 2)
return (-1);
// create my msgQ with key value from ftok()
// int qid = msgget(IPC_PRIVATE, IPC_EXCL|IPC_CREAT|0600);
int qid = atoi(av[1]);
// declare my message buffer
struct buf {
long mtype; // required
char greeting[50]; // mesg content
};
buf msg;
int size = sizeof(msg)-sizeof(long);
std::cout << "Welcome in the prog assignment 2! Type [exit] to stop the program." << std::endl;
bool exit = false;
while (!exit)
{
std::cout << getpid() << ": ";
std::cin.getline(msg.greeting, 50, '\n');
std::cout << msg.greeting << std::endl;
msg.mtype = 114; // only reading mesg with type mtype = 114
if (strcmp(msg.greeting, "exit") == 0)
exit = true;
msgsnd(qid, (struct msgbuf *)&msg, size, 0);
}
}
receiver
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <iostream>
#include <unistd.h>
#include <sys/wait.h>
#include <stdlib.h>
#include <stdio.h>
int main(int ac, char **av) {
int i = 0;
while (i < ac)
printf("AV: %s\n", av[i++]);
if (ac != 2)
return (-1);
// int qid = msgget(IPC_PRIVATE, IPC_EXCL|IPC_CREAT|0600);
int qid = atoi(av[1]);
// declare my message buffer
struct buf {
long mtype;
char greeting[50];
};
buf msg;
int size = sizeof(msg)-sizeof(long);
bool exit = false;
while (!exit)
{
msgrcv(qid, (struct msgbuf *)&msg, size, 114, 0);
if (strcmp(msg.greeting, "exit") == 0)
exit = true;
std::cout << getpid() << msg.greeting << std::endl;
}
std::cout << "get out" << std::endl;
}
It doesn't work and I'm not sure to understand why because, I'm creating the message queue, passing it as parameter, then I put it back as int and then use it. However, it just gives me an infinite loop of weird display, why?
ANy help is welcome.. Thank !

simple client/server program using named pipes in linux

I am trying to write a program that has two separate process that talk via named pipes. The client which sends a message to a server, and the server which needs to broadcast that message to all clients attached to it. So far, I can get a connection between the two, but I cannot get more than one message to work no matter what I have tried. Below is the code I have written that will allow a connection and transmission of a single message.
server.cpp:
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#define FIFO_FILE_1 "/tmp/client_to_server_fifo"
#define FIFO_FILE_2 "/tmp/server_to_client_fifo"
int main()
{
int client_to_server;
int server_to_client;
char buf[BUFSIZ];
/* create the FIFO (named pipe) */
mkfifo(FIFO_FILE_1, 0666);
mkfifo(FIFO_FILE_2, 0666);
printf("Server ON.\n");
while (1)
{
/* open, read, and display the message from the FIFO */
client_to_server = open(FIFO_FILE_1, O_RDONLY);
server_to_client = open(FIFO_FILE_2, O_WRONLY);
read(client_to_server, buf, BUFSIZ);
if (strcmp("exit",buf)==0)
{
printf("Server OFF.\n");
break;
}
else if (strcmp("",buf)!=0)
{
printf("Received: %s\n", buf);
printf("Sending back...\n");
write(server_to_client,buf,BUFSIZ);
}
/* clean buf from any data */
memset(buf, 0, sizeof(buf));
close(client_to_server);
close(server_to_client);
}
close(client_to_server);
close(server_to_client);
unlink(FIFO_FILE_1);
unlink(FIFO_FILE_2);
return 0;
}
client.cpp:
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <wait.h>
#include <string.h>
#define FIFO_FILE_1 "/tmp/client_to_server_fifo"
#define FIFO_FILE_2 "/tmp/server_to_client_fifo"
int main()
{
system("clear");
int client_to_server;
int server_to_client;
char str[140];
printf("Input message to server: ");
scanf("%139[^\r\n]", str);
/* write str to the FIFO */
client_to_server = open(FIFO_FILE_1, O_WRONLY);
server_to_client = open(FIFO_FILE_2, O_RDONLY);
if(write(client_to_server, str, sizeof(str)) < 0){
perror("Write:");//print error
exit(-1);
}
if(read(server_to_client,str,sizeof(str)) < 0){
perror("Read:"); //error check
exit(-1);
}
printf("\n...received from the server: %s\n\n\n",str);
close(client_to_server);
close(server_to_client);
/* remove the FIFO */
return 0;
}
close(client_to_server);
close(server_to_client);
Remove these lines from while loop because when server has done its work for the first time it will close the pipe and you cant be able to proceed further in pipes.