function does not return value in c - c

I have a behaviour that I don't understand.
When I call function get_bloccante_multimsg(...) doesn't return anything, read_m variable is not valorised and the next instruction is not executed.
The code below is a subpart of the program, hope that is helpful to identify the problem.
buffer.h
msg_t* get_bloccante_multimsg(int buffer, int C_id, int semid, const int N);
buffer.c
msg_t* get_bloccante_multimsg(int buffer, int C_id, int semid, const int N)
{
char* string;
char* shared_memory;
int *Cindex;
struct shmid_ds shmbuffer;
sb.sem_num = PIENE;
sb.sem_op = -1;
sb.sem_flg = 0;
if (semop(semid, &sb, 1) == -1) {
perror("semop() consumatore P(PIENE)");
exit(-9);
}
sb.sem_num = USO_T;
sb.sem_op = -1;
sb.sem_flg = 0;
if (semop(semid, &sb, 1) == -1) {
perror("semop() consumatore P(USO_T)");
exit(-9);
}
Cindex = shmat(C_id, NULL, 0);
shmctl(buffer, IPC_STAT, &shmbuffer);
shared_memory = (char *) shmat(buffer, (void *)0, 0);
memcpy(string, &shared_memory[*Cindex*20], 20);
*Cindex = (*Cindex + 1) % N;
shmdt(Cindex);
shmdt(shared_memory);
sb.sem_num = USO_T;
sb.sem_op = 1;
sb.sem_flg = 0;
if (semop(semid, &sb, 1) == -1) {
perror("semop() consumatore V(USO_T)");
exit(-9);
}
sb.sem_num = VUOTE;
sb.sem_op = 1;
sb.sem_flg = 0;
if (semop(semid, &sb, 1) == -1) {
perror("semop() consumatore V(VUOTE)");
exit(-9);
}
return msg_init_string(string);
}
main.c
msg_t *read_m;
for (int i = 0; i < C; i++)
{
// fork consumatore
cons_pid[i] = fork();
switch(cons_pid[i]) {
case -1: // fork fallita
exit(-5);
break;
case 0:
read_m = get_bloccante_multimsg(segment_id, C_id, semid, N);
printf("Messaggio in array: %s", (char *)getMessage(read_m));
exit(0);
break;
default:
break;
}
}
Thanks for your help.

In the function get_bloccante_multimsg(), the pointer to char string is used uninitialized in the line:
memcpy(string, &shared_memory[*Cindex*20], 20);
and later at:
return msg_init_string(string);
This leads to undefined behavior. You need to allocate space for the string and assign the address to string.

Related

Removing empty strings in an array of strings and other strange data in C

I'm creating a shell in C and have implemented piping. This involves dividing the argument on the left side and right side of the pipe into two separate array of strings to be executed separately with execvp. For some reason, the array of strings pcmd2 contains data other than the argument I entered in the shell.
For example, I enter ls | sort into the shell after running the program and it outputs the following: sort: open failed: : No such file or directory
Seeing this, I suspected that the array of strings pcmd2 containing the sort command may have empty strings and other things that are being processed.
I print out pcmd2 with a for-loop (with a new line after each string) and I find the following printed onto the screen:
sort
UJ
There clearly seems to be extra stuff in there. Seems like empty strings but I have no clue where the UJ is coming from (this gets consistenly printed out).
I've tried setting the index in pcmd2 that's right after where sort is stored in the array to NULL. Like so, pcmd2[1] = NULL and that seemed to "fix" it since the weird extra data would no longer be processed by the execvp function. However, that means that I can't pipe commands with multiple arguments like grep myshell as it would only be able to take in the grep part.
I will show the full code below because I'm unsure how much context is needed in this case.
I know there's some very broken piping implementation here (I've tried some weird solution to get it work with two pipes) but I'm working to just get one pipe to work. I'm not asking for help piping in particular.
The most relevant part, I believe, is in the splitPipeCommands function.
#include <stdio.h>
#include <sys/wait.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#define MAX_ARGS 20
#define MAX_PIPE_ARGS 3
#define BUFSIZE 1024
int input, output, append, usePipe;
char *inputFile;
char *outputFile;
FILE *fp1;
FILE *fp2;
int get_args(char* cmdline, char* args[])
{
int i = 0;
/* if no args */
if((args[0] = strtok(cmdline, "\n\t ")) == NULL)
return 0;
while((args[++i] = strtok(NULL, "\n\t ")) != NULL) {
if(i >= MAX_ARGS) {
printf("Too many arguments!\n");
exit(1);
}
}
/* the last one is always NULL */
return i;
}
void checkIORedirect(char* args[])
{
input = 0;
output = 0;
append = 0;
int i;
for(i = 0; args[i] != NULL; i++)
{
if(!strcmp(args[i], ">"))
{
output = 1;
outputFile = args[i+1];
args[i] = NULL;
}
else if(!strcmp(args[i], "<"))
{
input = 1;
inputFile = args[i+1];
args[i] = NULL;
//printf("inputFile: %s\n", inputFile);
}
else if(!strcmp(args[i], ">>"))
{
append = 1;
outputFile = args[i+1];
args[i] = NULL;
}
}
}
int getPipeIndexes(char* args[], int* pIndex1, int* pIndex2)
{
*pIndex1 = -1;
*pIndex2 = -1;
int i = 0;
int pcount = 0;
usePipe = 0;
for(i = 0; args[i] != NULL; i++)
{
if(!strcmp(args[i], "|") && pcount == 0)
{
//printf("First pipe!\n");
*pIndex1 = i;
args[i] = NULL;
pcount++;
usePipe = 1;
}
else if(!strcmp(args[i], "|") && pcount == 1)
{
//printf("Second pipe!\n");
*pIndex2 = i;
args[i] = NULL;
pcount++;
}
else if(!strcmp(args[i], "|") && pcount > 1)
{
printf("Too many pipes, only accepting first two!\n");
args[i] = NULL;
}
}
return pcount;
}
void splitPipeCommands(char* args[], int* pIndex1, int* pIndex2, int pcount, char* pcmd1[], char* pcmd2[], char* pcmd3[])
{
if(pcount == 1)
{
int i;
int cmdIndex = 0;
for(i = 0; i < *pIndex1; i++)
{
pcmd1[cmdIndex] = args[i];
cmdIndex++;
}
cmdIndex = 0;
//printf("2nd half of args: \n");
for(i = *pIndex1 + 1; args[i] != NULL; i++)
{
pcmd2[cmdIndex] = args[i];
//printf("%s\n", args[i]);
cmdIndex++;
}
//pcmd2[1] = NULL;
//*pcmd1 = args[0];
//*pcmd2 = args[*pIndex1 + 1];
/*TODO: del when you finish debugging*/
//printf("pcmd1=%s,%s,%s\n", pcmd1[0], pcmd1[1], pcmd1[2]);
//printf("pcmd2=%s\n", pcmd2[0]);
}
else if(pcount == 2)
{
int i;
int cmdIndex = 0;
for(i = 0; i < *pIndex1; i++)
{
pcmd1[cmdIndex] = args[i];
cmdIndex++;
}
cmdIndex = 0;
for(i = *pIndex1 + 1; i < *pIndex2; i++)
{
pcmd2[cmdIndex] = args[i];
cmdIndex++;
}
//pcmd2[1] = NULL;
cmdIndex = 0;
for(i = *pIndex2 + 1; args[i] != NULL; i++)
{
pcmd3[cmdIndex] = args[i];
cmdIndex++;
}
/*
*pcmd1 = args[0];
*pcmd2 = args[*pIndex1 + 1];
*pcmd3 = args[*pIndex2 + 1];
*/
/*TODO: del when you finish debugging*/
//printf("pcmd1=%s,", *pcmd1);
//printf("pcdm2=%s,", *pcmd2);
//printf("pcmd3=%s\n", *pcmd3);
}
}
void closeFiles()
{
if(fp1 != NULL)
{
fclose(fp1);
}
if(fp2 != NULL)
{
fclose(fp2);
}
}
void execute(char* cmdline)
{
int pid, pid2, async;
char* args[MAX_ARGS];
int nargs = get_args(cmdline, args);
if(nargs <= 0) return;
if(!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) {
exit(0);
}
/* check if async call */
if(!strcmp(args[nargs-1], "&")) { async = 1; args[--nargs] = 0; }
else async = 0;
/*Pipe related*/
int pIndex1, pIndex2;
char* pcmd1[30];
char* pcmd2[30];
char* pcmd3[30];
int pcount = getPipeIndexes(args, &pIndex1, &pIndex2);
if(usePipe)
{
splitPipeCommands(args, &pIndex1, &pIndex2, pcount, pcmd1, pcmd2, pcmd3);
if(pcount == 1)
{
checkIORedirect(pcmd1);
checkIORedirect(pcmd2);
}
else if(pcount == 2)
{
checkIORedirect(pcmd1);
checkIORedirect(pcmd2);
checkIORedirect(pcmd3);
}
}
else
{
checkIORedirect(args);
}
/*TODO: del when finished debugging*/
//printf("pIndex1=%d,pIndex2=%d,pcount=%d\n", pIndex1, pIndex2, pcount);
//checkIORedirect(args);
if(output)
{
if((fp1 = fopen(outputFile, "w")) == NULL)
{
printf("Output to file failed!\n");
}
}
else if(append)
{
if((fp1 = fopen(outputFile, "a")) == NULL)
{
printf("Append to file failed!\n");
}
}
if(input)
{
if((fp2 = fopen(inputFile, "r")) == NULL)
{
printf("Input from file failed!\n");
}
}
int fd[2];
int fd2[2];
if(usePipe)
{
if(pipe(fd) == -1)
{
perror("pipe failed");
exit(1);
}
}
pid = fork();
if(pid == 0) { /* child process */
if(input)
{
//printf("Input\n");
dup2(fileno(fp2), STDIN_FILENO);
fclose(fp2);
input = 0;
}
if(output || append)
{
dup2(fileno(fp1), STDOUT_FILENO);
fclose(fp1);
output = 0;
append = 0;
//printf("Output or append\n");
}
if(usePipe)
{
//TODO: Make case for one pipe and two pipes
if(pcount == 2)
{
if(pipe(fd2) == -1)
{
perror("pipe failed");
exit(1);
}
pid2 = fork();
if(pid2 == -1)
{
perror("fork 2 failed");
exit(1);
}
if(pid2 == 0) //Child 2
{
close(fd[1]);
close(fd[0]);
close(fd2[1]);
dup2(fd2[0], 0);
close(fd2[0]);
execvp(pcmd2[0], pcmd2);
perror("exec second child failed");
exit(-1);
}
else //Child 1
{
close(fd[1]);
dup2(fd[0], 0);
close(fd[0]);
close(fd2[0]);
dup2(fd2[1], 1);
close(fd2[1]);
execvp(pcmd3[0], pcmd3);
perror("exec first child failed");
exit(-1);
}
}
else if(pcount == 1)
{
//TODO: pipe for one pipe
//close(fd[1]);
//dup2(fd[0], 0);
dup2(fd[1], STDOUT_FILENO);
close(fd[0]);
close(fd[1]);
printf("pcmd1=%s\n", pcmd1[0]);
execvp(pcmd1[0], pcmd1);
perror("exec child failed");
exit(-1);
}
}
else
{
execvp(args[0], args);
/* return only when exec fails */
perror("exec failed");
exit(-1);
}
/*
execvp(args[0], args);
// return only when exec fails
perror("exec failed");
exit(-1);
*/
} else if(pid > 0) { /* parent process */
if(usePipe)
{
pid=fork();
if(pid==0)
{
dup2(fd[0], STDIN_FILENO);
close(fd[1]);
close(fd[0]);
printf("pcmd2 contents: \n");
int j;
for(j = 0; pcmd2[j] != NULL; j++)
{
printf("%s\n", pcmd2[j]);
}
//FIXME: Something's wrong with pcmd2
execvp(pcmd2[0], pcmd2);
//execlp("sort", "sort", (char*)NULL);
perror("exec second command failed");
}
else
{
int status;
close(fd[0]);
close(fd[1]);
waitpid(pid, &status, 0);
}
//wait(NULL);
/*
close(fd[0]);
dup2(fd[1], 1);
printf("pcmd1=%s\n", pcmd1[0]);
execvp(pcmd1[0], pcmd1);
perror("exec parent failed");
*/
}
if(!async)
{
waitpid(pid, NULL, 0);
}
else
{
printf("this is an async call\n");
}
} else { /* error occurred */
perror("fork failed");
exit(1);
}
}
int main (int argc, char* argv [])
{
char cmdline[BUFSIZE];
for(;;) {
printf("COP4338$ ");
if(fgets(cmdline, BUFSIZE, stdin) == NULL) {
perror("fgets failed");
exit(1);
}
execute(cmdline);
usePipe = 0;
//closeFiles();
fflush(stdout);
}
return 0;
}

Semaphore values are not changing in Ubuntu

I'm trying to create a solution for the River Crossing Problem from "The Little Book of Semaphores" (Chapter 5, section 7, page 148), I'm using an Ubuntu virtual machine in my PC.
The problem is that the semaphores I created are not changing values, all of them stay at 0, I'm using four files.
What I do is, run buffer and then create two hacker processes and then two serf processes, the thing is that the "Boarding a X" message is printed before the boat is filled (at least four passengers) and when I print the semaphore values all of them are in 0.
header.h, where I declare Semaphore ids and operations:
#ifndef SEMAFOROS_H
#define SEMAFOROS_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ipc.h>
#include <sys/sem.h>
#include <sys/shm.h>
#define BARRIER 10
#define MUTEX 11
#define SERFQUEUE 12
#define HACKERQUEUE 13
struct buffer {
int hackers;
int serfs;
};
int sem_wait(int semid, int sem_num, int val) {
struct sembuf op;
op.sem_num = sem_num;
op.sem_op = -val;
op.sem_flg = 0;
return semop(semid, &op, 1);
}
int sem_signal(int semid, int sem_num, int val) {
struct sembuf op;
op.sem_num = sem_num;
op.sem_op = val;
op.sem_flg = 0;
return semop(semid, &op, 1);
}
int mutex_wait(int semid, int sem_num) {
return sem_wait(semid, sem_num, 1);
}
int mutex_signal(int semid, int sem_num) {
return sem_signal(semid, sem_num, 1);
}
#endif
buffer.c, where I create the semaphores:
#include "header.h"
int main(int argc, char* argv[])
{
int semid, shmid, i;
key_t key;
if (argc != 1) {
printf("usage: %s\n", argv[0]);
return -1;
}
if ( (key = ftok("/dev/null", 65)) == (key_t) -1 ) {
perror(argv[0]);
return -1;
}
if ( (semid = semget(key, 4, 0666 | IPC_CREAT)) < 0 ) {
perror(argv[0]);
return -1;
}
semctl(semid, BARRIER, SETVAL, 4);
semctl(semid, MUTEX, SETVAL, 1);
semctl(semid, SERFQUEUE, SETVAL, 0);
semctl(semid, HACKERQUEUE, SETVAL, 0);
unsigned short final_values[4];
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
if ( (shmid = shmget(key, sizeof(struct buffer), 0666 | IPC_CREAT)) < 0) {
semctl(semid, 0, IPC_RMID, 0);
perror("shmget");
return -1;
}
struct buffer *b = (struct buffer *) shmat(shmid, (void *) 0, 0);
b->hackers = 0;
b->serfs = 0;
shmdt(b);
return 0;
}
hackers.c, code for hackers:
#include "header.h"
#include <time.h>
void a_hacker(char* program) {
int semid, shmid, i, k, isCaptain = 0;
key_t key;
struct buffer *b;
if ( (key = ftok("/dev/null", 65)) == (key_t) -1 ) {
perror(program);
exit(-1);
}
if ( (semid = semget(key, 4, 0666)) < 0 ) {
perror(program);
exit(-1);
}
if ( (shmid = shmget(key, sizeof(struct buffer), 0666)) < 0 ) {
perror("shmid");
exit(-1);
}
b = (struct buffer *) shmat(shmid, (void *) 0, 0);
mutex_wait(semid, MUTEX);
b->hackers += 1;
if (b->hackers == 4) {
sem_signal(semid, HACKERQUEUE, 4);
b->hackers = 0;
isCaptain = 1;
} else if (b->hackers == 2 && b->serfs >= 2) {
sem_signal(semid, HACKERQUEUE, 2);
sem_signal(semid, SERFQUEUE, 2);
b->hackers = 0;
b->serfs -= 2;
isCaptain = 1;
} else {
mutex_signal(semid, MUTEX);
}
unsigned short final_values[4];
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, HACKERQUEUE, 1);
printf("Boarding a hacker\n");
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, BARRIER, 1);
if (isCaptain) {
printf("Fugaaaa\n");
mutex_signal(semid, MUTEX);
}
sem_signal(semid, BARRIER, 2);
shmdt(b);
exit(0);
}
int main(int argc, char* argv[]) {
int amount_hackers = 0, semid, i, pid;
key_t key;
if (argc != 2) {
printf("usage: %s amount_of_serfs amount_of_hackers\n", argv[0]);
return -1;
}
amount_hackers = atoi(argv[1]);
if (amount_hackers < 1) {
printf("%s: The amount_of_hackers must be a positive number greater than zero.\n", argv[0]);
return -1;
}
for (i = 0; i < amount_hackers; i++) {
if ( (pid = fork()) < 0 ) {
perror("fork");
return -1;
} else if (pid == 0) {
a_hacker(argv[0]);
} else {
}
}
return 0;
}
serfs.c, code for serfs:
#include "header.h"
#include <time.h>
void a_serf(char* program) {
int semid, shmid, i, k, isCaptain = 0;
key_t key;
struct buffer *b;
if ( (key = ftok("/dev/null", 65)) == (key_t) -1 ) {
perror(program);
exit(-1);
}
if ( (semid = semget(key, 4, 0666)) < 0 ) {
perror(program);
exit(-1);
}
if ( (shmid = shmget(key, sizeof(struct buffer), 0666)) < 0 ) {
perror("shmid");
exit(-1);
}
b = (struct buffer *) shmat(shmid, (void *) 0, 0);
mutex_wait(semid, MUTEX);
b->serfs += 1;
if (b->serfs == 4) {
sem_signal(semid, SERFQUEUE, 4);
b->serfs = 0;
isCaptain = 1;
} else if (b->hackers == 2 && b->serfs >= 2) {
sem_signal(semid, HACKERQUEUE, 2);
sem_signal(semid, SERFQUEUE, 2);
b->serfs = 0;
b->hackers -= 2;
isCaptain = 1;
} else {
mutex_signal(semid, MUTEX);
}
unsigned short final_values[4];
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, SERFQUEUE, 1);
printf("Boarding a serf\n");
semctl(semid, 0, GETALL, final_values);
for (i = 0; i < 4; i++) {
printf("%3i", final_values[i]);
}
printf("\n");
sem_wait(semid, BARRIER, 1);
if (isCaptain) {
printf("Fugaaaa\n");
mutex_signal(semid, MUTEX);
}
sem_signal(semid, BARRIER, 2);
shmdt(b);
exit(0);
}
int main(int argc, char* argv[]) {
int amount_serfs = 0, semid, i, pid;
key_t key;
if (argc != 2) {
printf("usage: %s amount_of_serfs amount_of_hackers\n", argv[0]);
return -1;
}
amount_serfs = atoi(argv[1]);
if (amount_serfs < 1) {
printf("%s: The amount_of_serfs must be a positive number greater than zero.\n", argv[0]);
return -1;
}
for (i = 0; i < amount_serfs; i++) {
if ( (pid = fork()) < 0 ) {
perror("fork");
return -1;
} else if (pid == 0) {
a_serf(argv[0]);
} else {
}
}
return 0;
}
Can someone please help me?

tail exec doesn't work well in pipe (No output until parent process die!)

#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
int pipFd[1000][2], hasPipe, forked, pipNum = 0, pNum = 0, bPipe = 0, bpipFd[2], stPipe, InpToChld = 0;
pid_t pid[1000];
void * outInp;
int builtin_command(char **argv)
{
if (!strcmp(argv[0], "quit")) /* quit command */
exit(0);
if (!strcmp(argv[0], "&")) /* Ignore singleton & */
return 1;
return 0; /* Not a builtin command */
}
int parsecmd(char *buf, char **argv)
{
char *delim; /* Points to first space delimiter */
int argc; /* Number of args */
int bg; /* Background job? */
buf[strlen(buf) - 1] = ' '; /* Replace trailing '\n' with space */
while (*buf && (*buf == ' ')) /* Ignore leading spaces */
buf++;
/* Build the argv list */
argc = 0;
while ((delim = strchr(buf, ' ')))
{
argv[argc++] = buf;
*delim = '\0';
buf = delim + 1;
while (*buf && (*buf == ' ' || *buf == '<')) /* Ignore spaces */
buf++;
}
argv[argc] = NULL;
if (argc == 0) /* Ignore blank line */
return 1;
/* Should the job run in the background? */
if ((bg = (*argv[argc - 1] == '&')) != 0)
argv[--argc] = NULL;
return argc;
}
void myExec(char **argv, char *buf)
{
// if ((pid[pNum] = fork()) == 0)
// {
strcpy(buf, "/bin/");
buf[5] = 0;
strcat(buf, argv[0]);
//printf("%s\n", buf);
if (execv(buf, argv) < 0)
{
memset(buf, 0, 255);
strcpy(buf, "/usr/bin/");
strcat(buf, argv[0]);
if (execv(buf, argv) < 0)
{
printf("exec failed\n");
exit(-1);
}
}
exit(0);
// }
// else
// wait(NULL);
}
int splitPipe(char **cmdLine)
{
static char *svBuftok;
if (!hasPipe)
*cmdLine = strtok_r(*cmdLine, "|", &svBuftok);
else{
//printf("--------%s\n", svBuftok);
*cmdLine = strtok_r(svBuftok, "|", &svBuftok);
}
//printf(".......................%s %s\n", svBuftok, *cmdLine);
return strlen(svBuftok);
}
int isDigit(char * strings){
int i, tmp = strlen(strings);
for(i = 0; i < tmp; i++){
if(strings[i] < '0' || strings[i] > '9') return 0;
}
return 1;
}
void handler(int sig)
{
if (sig == SIGINT && forked) exit(0);
}
static char *getcmd()
{
static char buf[256];
//fputs("> ", stdout);
//printf("asdfasdfasdf\n");
fflush(stdin);
fflush(stdout);
if (fgets(buf, sizeof(buf), stdin) == NULL)
return NULL;
if (buf[strlen(buf)] == '\n')
buf[strlen(buf)] = 0;
return buf;
}
int main()
{
char *cmdline;
char *argv[12000];
char c, dir[256], buf[256], rdBuf[100000], pipBuf[100000];
int status, fd, rfd, dest, argc;
pid_t tmpPid;
getcwd(dir, 256);
signal(SIGINT, handler);
signal(SIGTSTP, handler);
signal(SIGCHLD, handler);
signal(30, handler);
//outInp = &&Outinp;
//printf("gd\n");
while (cmdline = getcmd())
{
ret:
do
{
rfd = 0;
hasPipe = splitPipe(&cmdline);
//printf(":::::::::::::::%s %d\n", cmdline, hasPipe);
if (strlen(cmdline) <= 1)
continue;
argc = parsecmd(cmdline, argv);
if (!builtin_command(argv))
{
if(!strcmp(argv[0], "exit")) exit(0);
{
if(hasPipe) pipe(pipFd[pNum]);
if(!bPipe) pipe(bpipFd);
fflush(NULL);
if((pid[pNum] = fork()) == 0){
int ofd, svStdout = dup(1), svStin = dup(0);
forked = 1;
close(pipFd[pNum][0]);
//printf("%s %d\n",argv[0], getpid());
//fflush(stdout);
//printf("\n");
if(bPipe) {
close(pipFd[pNum - 1][1]);
dup2(pipFd[pNum - 1][0], STDIN_FILENO);
}
else{
close(bpipFd[1]);
dup2(bpipFd[0], STDIN_FILENO);
}
//addArgv(pipBuf, &argc, argv);
if(hasPipe) dup2(pipFd[pNum][1], 1);
if(!strcmp(argv[argc - 2], ">")){
//printf("chked %s\n", argv[argc - 1]);
remove(argv[argc - 1]);
ofd = open(argv[argc - 1], O_WRONLY | O_CREAT, 0755);
dup2(ofd, 1);
argc -= 2;
argv[argc] = NULL;
}
else if(!strcmp(argv[argc - 2], ">>")){
//printf("chked %s\n", argv[argc - 1]);
ofd = open(argv[argc - 1], O_WRONLY);
dup2(ofd, 1);
argc -= 2;
argv[argc] = NULL;
}
fflush(stdout);
myExec(argv, buf);
close(pipFd[pNum][1]);
if(bPipe) {
close(pipFd[pNum - 1][0]);
}
else{
close(bpipFd[0]);
}
dup2(svStin, 0);
dup2(svStdout, 1);
if(!strcmp(argv[argc - 2], ">")) close(ofd);
exit(0);
}
else{
if(!bPipe) {
close(bpipFd[0]);
stPipe = pid[pNum];
InpToChld = 1;
}
pNum++;
}
}
bPipe = hasPipe;
}
}while (hasPipe);
while(InpToChld){
memset(rdBuf, 0, sizeof(rdBuf)); int i;
fflush(NULL);
//printf("Inp~~\n");
if(read(0, rdBuf, sizeof(rdBuf)) == 0){
write(bpipFd[1], "\0", 1);
InpToChld = 0;
break;
}
if(write(bpipFd[1], rdBuf, strlen(rdBuf)) < 0){
cmdline = rdBuf;
InpToChld = 0;
goto ret;
}
fflush(NULL);
//fflush(stdout);
}
}
}
At first, exec to tail works well.
But tail's output doesn't be printed until parent process die.
for example, cat < /proc/meminfo | head works well
but cat < /proc/meminfo | tail is printed after exit parent.
I guess this is about input / output problem, but I can't solve this problem.
The steps to code a tiny shell :
handle SIGCHLD
if necessary handle redirect
if necessary handle pipe
The following code could work, not handle builtin command:
#include <ctype.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
void signal_SIGCHLD_handle(int sig) {
while (waitpid(-1, NULL, WNOHANG) > 0)
;
}
int main()
{
char buf[256];
while (fgets(buf, sizeof(buf), stdin) != NULL) {
if (fork() > 0) { // parent
wait(NULL);
continue;
}
//child
// handle SIGCHLD
struct sigaction act;
act.sa_handler = signal_SIGCHLD_handle;
sigemptyset(&act.sa_mask);
act.sa_flags = SA_RESTART;
sigaction(SIGCHLD, &act, NULL);
if (buf[strlen(buf)] == '\n')
buf[strlen(buf)] = '\0';
for (char* next_cmd = strtok(buf, "|"); next_cmd != NULL; ) {
char* current_cmd = next_cmd;
next_cmd = strtok(NULL, "|");
char* argv[10];
int argv_index = 0;
int new_argv = 1;
for (;;) {
if(*current_cmd == '\0') {
argv[argv_index] = NULL;
break;
}
if (isspace(*current_cmd)) {
*current_cmd++ = '\0';
new_argv = 1;
continue;
}
if (*current_cmd == '<') {
++current_cmd;
while (isspace(*current_cmd))
++current_cmd;
if (*current_cmd == '\0') {
printf("Please use cmd < file_name");
return -1;
}
char* filename = current_cmd;
while (!isspace(*current_cmd) && *current_cmd != '\0')
++current_cmd;
if (*current_cmd != '\0')
*current_cmd++ = '\0';
int fd = open(filename, O_RDONLY);
if (fd < 0) {
perror("<");
return -1;
}
dup2(fd, 0);
close(fd);
continue;
}
if (*current_cmd == '>') {
int add = 0;
if (*++current_cmd == '>') {
add = 1;
++current_cmd;
}
while (isspace(*current_cmd))
++current_cmd;
if (*current_cmd == '\0') {
printf(add == 0 ? "Please use cmd > file_name" : "Please use cmd >> file_name");
return -1;
}
char* filename = current_cmd;
while (!isspace(*current_cmd) && *current_cmd != '\0')
++current_cmd;
if (*current_cmd != '\0')
*current_cmd++ = '\0';
int fd = open(filename, add == 0 ? (O_WRONLY|O_CREAT) : (O_WRONLY|O_CREAT|O_APPEND), 0644);
if (fd < 0) {
perror(add == 0 ? ">" : ">>");
return -1;
}
dup2(fd, 1);
close(fd);
continue;
}
if (new_argv == 1) {
new_argv = 0;
argv[argv_index++] = current_cmd;
}
++current_cmd;
}
if (argv_index == 0)
continue;
if (next_cmd != NULL) {
int pipe_fd[2];
pipe(pipe_fd);
if (fork() == 0) {
close(pipe_fd[0]);
dup2(pipe_fd[1], STDOUT_FILENO);
close(pipe_fd[1]);
execvp(argv[0], argv);
return -1;
}
close(pipe_fd[1]);
dup2(pipe_fd[0], STDIN_FILENO);
close(pipe_fd[1]);
continue;
}
execvp(argv[0], argv);
}
}
return 0;
}

TCP server not waiting for client response?

I have been given the task to write a Roulette game, using TCP socket programming in C.
The code was working just fine, until I got close to finishing it, and for some unknown reason, it stopped working properly and I can't track down the error.
The code used to work with simple recv() calls, so I tried making the readn() function (actually got it from another post), however it did not solve the issue.
I might be overlooking the problem, which lies in the for (int i = 0 ; i < max_round ; i++) loop of the main() function.
Here is my server:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
int
readn(int f, void *av, int n)
{
char *a;
int m, t;
a = av;
t = 0;
while(t < n){
m = read(f, a+t, n-t);
if(m <= 0){
if(t == 0)
return m;
break;
}
t += m;
}
return t;
}
typedef struct
{
int _count, _bet, _client, _currency;
int _numbers[3];
char *_color;
} Roulette;
int find_element(int searched, int numbers[], int count)
{
for (int i = 0; i < count; i++)
{
if (searched == numbers[i])
return 1;
}
return 0;
}
void Round_Results(Roulette *obj1, Roulette *obj2, const int size)
{
char *lose_msg = "Sajnos nem nyert ebben a korben!\n";
char *win_msg = "Gratulalok, ebben a korben nyert!\n";
char answer[size];
srand(time(NULL));
int winner_number = rand() % 10;
if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 0) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 0))
{
send(obj1->_client, lose_msg, size, 0);
obj1->_currency = obj1->_currency - obj1->_bet;
printf("%d", obj1->_currency);
sprintf(answer, "%d", obj1->_currency);
send(obj1->_client, answer, size, 0);
send(obj2->_client, lose_msg, size, 0);
obj2->_currency = obj2->_currency - obj2->_bet;
printf("%d", obj2->_currency);
sprintf(answer, "%d", obj2->_currency);
send(obj2->_client, answer, size, 0);
}
else if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 1) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 0))
{
send(obj1->_client, win_msg, size, 0);
obj1->_currency = obj1->_currency + obj1->_bet * (6 / obj1->_count);
printf("%d", obj1->_currency);
sprintf(answer, "%d", obj1->_currency);
send(obj1->_client, answer, size, 0);
send(obj2->_client, lose_msg, size, 0);
obj2->_currency = obj2->_currency - obj2->_bet;
printf("%d", obj2->_currency);
sprintf(answer, "%d", obj2->_currency);
send(obj2->_client, answer, size, 0);
}
else if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 0) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 1))
{
send(obj1->_client, lose_msg, size, 0);
obj1->_currency = obj1->_currency - obj1->_bet;
printf("%d", obj1->_currency);
sprintf(answer, "%d", obj1->_currency);
send(obj1->_client, answer, size, 0);
send(obj2->_client, win_msg, size, 0);
obj2->_currency = obj2->_currency + obj2->_bet * (6 / obj2->_count);
printf("%d", obj2->_currency);
sprintf(answer, "%d", obj2->_currency);
send(obj2->_client, answer, size, 0);
}
else if ((find_element(winner_number, obj1->_numbers, obj1->_count) == 1) && (find_element(winner_number, obj1->_numbers, obj1->_count) == 1))
{
send(obj1->_client, win_msg, size, 0);
obj1->_currency = obj1->_currency + obj1->_bet * (6 / obj1->_count);
printf("%d", obj2->_currency);
sprintf(answer, "%d", obj2->_currency);
send(obj1->_client, answer, size, 0);
send(obj2->_client, win_msg, size, 0);
obj2->_currency = obj2->_currency + obj2->_bet * (6 / obj1->_count);
printf("%d", obj2->_currency);
sprintf(answer, "%d", obj2->_currency);
send(obj2->_client, answer, size, 0);
}
}
void Initialize(int client, int count, int numbers[], int bet, char *color, Roulette *obj)
{
obj->_client = client;
obj->_count = count;
obj->_color = color;
obj->_bet = bet;
for (int i = 0; i < count; i++)
obj->_numbers[i] = numbers[i];
}
void Round_Information(int client, const int size, Roulette *obj)
{
char *message = malloc(size);
char *money_msg = "Mennyi zsetonba fogad?\n";
char *number_msg = "Melyik szamra fogad?\n[0-9]\n";
char *count_msg = "Mennyi szamra fogad?\n[1-3]\n";
char *color_msg = "Milyen szinre fogad?\n[black/red]\n";
int count = 0;
char *color;
int numbers[3];
int bet;
//Bet
send(client, money_msg, size, 0);
readn(client,message,size);
bet = atoi(message);
//Count
send(client, count_msg, size, 0);
readn(client,message,size);
count = atoi(message);
//Number/Numbers
for (int i = 0; i < count; i++)
{
send(client, number_msg, size, 0);
readn(client,message,size);
numbers[i] = atoi(message);
}
//Color
send(client, color_msg, size, 0);
readn(client,message,size);
color = message;
Initialize(client, count, numbers, bet, color, obj);
free(message);
return 0;
}
int main(int argc, char **argv)
{
if (argc < 2)
{
printf("tul keves argumentum!\nusage : ./valami PORT_NR\n");
exit(-1);
}
const int size = 50;
int max_round, starting_money;
int flag = 0;
int on = 1;
char *message = malloc(size);
char *round_msg = "Korok szama :\n";
char *greeting_msg = "Sikeresen csatlakozott a szerverre!\n";
char *waiting_msg = "A masik jatekosra varunk!\n";
char *win_msg = "Gratulalok !\nMegnyerte a jatekot!\n";
char *lose_msg = "Jatek vege !\nSajnos nem nyert!\n";
Roulette *obj1 = malloc(size);
Roulette *obj2 = malloc(size);
int server_socket = socket(AF_INET, SOCK_STREAM, flag);
if (server_socket < 0)
{
printf("Nem sikerult a socket-et letrehozni\n");
exit(-1);
}
struct sockaddr_in server_adress;
server_adress.sin_addr.s_addr = INADDR_ANY;
server_adress.sin_family = AF_INET;
server_adress.sin_port = atoi(argv[1]);
setsockopt(server_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on));
setsockopt(server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
int binding_server = bind(server_socket, (struct sockaddr *)&server_adress, sizeof(server_adress));
if (binding_server < 0)
{
printf("nem sikerult bindolni a szervert!\n");
exit(-1);
}
listen(server_socket, 2);
int client1 = accept(server_socket, NULL, NULL);
int client2 = accept(server_socket, NULL, NULL);
send(client1, greeting_msg, size, flag);
send(client2, greeting_msg, size, flag);
printf("Milyen hosszu legyen a jatek ? (Hany kor)\n");
scanf("%s", message);
max_round = atoi(message);
//Korok szama
send(client1, message, size, flag);
send(client2, message, size, flag);
printf("Mennyi zsetonnal kezdodjon a jatek?\n");
scanf("%s", message);
starting_money = atoi(message);
//Kezdo penz
send(client1, message, size, flag);
send(client2, message, size, flag);
obj1->_currency = starting_money;
obj2->_currency = starting_money;
for (int i = 0; i < max_round; i++)
{
Round_Information(client1, size, obj1);
Round_Information(client2, size, obj2);
Round_Results(obj1, obj2, size);
}
if (obj1->_currency > obj2->_currency)
{
send(obj1->_client, win_msg, size, flag);
send(obj2->_client, lose_msg, size, flag);
}
else if (obj1->_currency < obj2->_currency)
{
send(obj2->_client, win_msg, size, flag);
send(obj1->_client, lose_msg, size, flag);
}
else
{
send(obj1->_client, lose_msg, size, flag);
send(obj2->_client, lose_msg, size, flag);
}
close(client1);
close(client2);
close(server_socket);
free(message);
free(obj1);
free(obj2);
return 0;
}
Here is the Client:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
void Round_Information(int client, const int size, int currency)
{
char *message = malloc(size);
char answer[size];
char *black = "black";
char *red = "red";
int count = 0;
memset(answer, 0, size);
//Bet
recv(client, message, size, 0);
if (currency == 0)
{
printf("Game over!\nVeszitett!\n");
close(client);
}
while (atoi(answer) < 1 || atoi(answer) > currency)
{
if (strcmp(answer, "befejeztem"))
{
close(client);
}
printf("%s", message);
scanf("%s", answer);
}
if (strcmp(answer, "befejeztem"))
{
close(client);
}
send(client, answer, size, 0);
answer[0] = '0';
//Count
recv(client, message, size, 0);
while (atoi(answer) < 1 || atoi(answer) > 3)
{
if (strcmp(answer, "befejeztem"))
{
close(client);
}
printf("%s", message);
scanf("%s", answer);
}
count = atoi(answer);
if (strcmp(answer, "befejeztem"))
{
close(client);
}
send(client, answer, size, 0);
//Number/Numbers
for (int i = 0; i < count; i++)
{
recv(client, message, size, 0);
answer[0] = 'z';
while (atoi(answer) <= 0 || atoi(answer) > 9)
{
if (strcmp(answer, "befejeztem"))
{
close(client);
}
printf("%s", message);
scanf("%s", answer);
}
if (strcmp(answer, "befejeztem"))
{
close(client);
}
send(client, answer, size, 0);
}
//Color
recv(client, message, size, 0);
while ((strcmp(answer, black) != 0) && (strcmp(answer, red) != 0))
{
if (strcmp(answer, "befejeztem"))
{
close(client);
}
printf("%s", message);
scanf("%s", answer);
}
if (strcmp(answer, "befejeztem"))
{
close(client);
}
send(client, answer, size, 0);
free(message);
}
void Round_Results(int client_socket, char *message, const int size, int *currency)
{
recv(client_socket, message, size, 0);
printf("%s\n", message);
recv(client_socket, message, size, 0);
(*currency) = atoi(message);
}
int main(int argc, char **argv)
{
if (argc < 2)
{
printf("tul keves argumentum!\nusage : ./valami PORT_NR\n");
exit(-1);
}
const int size = 50;
int flag = 0;
int max_round, currency;
int on = 1;
char message[size];
int client_socket = socket(AF_INET, SOCK_STREAM, flag);
if (client_socket < 0)
{
printf("Nem sikerult a socketet letrehozni!\n");
exit(-1);
}
struct sockaddr_in server_adress;
server_adress.sin_addr.s_addr = INADDR_ANY;
server_adress.sin_family = AF_INET;
server_adress.sin_port = atoi(argv[1]);
setsockopt(client_socket, SOL_SOCKET, SO_KEEPALIVE, (char *)&on, sizeof(on));
setsockopt(client_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on));
int connection = connect(client_socket, (struct sockaddr *)&server_adress, sizeof(server_adress));
if (connection < 0)
{
printf("Nem sikerult kapcsolodni a szerverhez!\n");
exit(-1);
}
//Sikeres kapcsolodas
int receive = recv(client_socket, message, size, flag);
if (receive < 0)
{
printf("Nem sikerult megkapni az uzenetet!\n");
exit(-1);
}
printf("%s", message);
//Korok szama
receive = recv(client_socket, message, size, flag);
if (receive < 0)
{
printf("Nem sikerult megkapni az uzenetet!\n");
exit(-1);
}
printf("Korok szama :%s\n", message);
max_round = atoi(message);
//Kezdo penz
receive = recv(client_socket, message, size, flag);
if (receive < 0)
{
printf("Nem sikerult megkapni az uzenetet!\n");
exit(-1);
}
printf("Jelenlegi zsetonok mennyisege :%s\n", message);
currency = atoi(message);
for (int i = 0; i < max_round; i++)
{
Round_Information(client_socket, size, currency);
Round_Results(client_socket, message, size, &currency);
printf("Jelenlegi zseton :%d\n", currency);
}
recv(client_socket, message, size, flag);
printf("%s\n", message);
close(client_socket);
return 0;
}
It was not easy to read, since i do not know what the outputs mean, but i think i found your problem.
if (strcmp(answer, "befejeztem"))
{
close(client);
}
strcmp is 0 when the strings are equal. That means in almost every case you close the socket. Actually in the first loop answer is zero that means you are closing the socket right away. If you close the socket but the server tries to send data the program will receive the SIGPIPE signal and i think the default handler will just abort the program.
Try to change all these if statements to:
if(!strcmp(answer, "befejeztem"))
{
close(client);
}

IRB fails to run ruby gem function while ruby is successful

I recently made the following ruby gem (called sse):
#include <ruby.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <time.h>
#include <signal.h>
/*
* Module handle
*/
static VALUE sse_module;
/*
* All exceptions for this module
*/
static VALUE sse_FileNotFoundError;
static VALUE sse_ForkFailureError;
static VALUE sse_PipeFailureError;
static VALUE sse_WriteFailureError;
static VALUE sse_ReadFailureError;
static VALUE sse_WaitpidFailureError;
static VALUE sse_TimeoutError;
/*
* General utilities
*/
char **split(char *str, char *sep) {
char *arg = strtok(str, sep);
size_t arg_list_size = 1;
char **arg_list = malloc(sizeof(char*));
arg_list[0] = malloc(strlen(arg));
strncpy(arg_list[0], arg, strlen(arg));
while((arg = strtok(NULL, sep)) != NULL) {
arg_list = realloc(arg_list, (sizeof(char*))*(arg_list_size+1));
arg_list[arg_list_size] = malloc(strlen(arg));
strncpy(arg_list[arg_list_size], arg, strlen(arg));
++arg_list_size;
}
arg_list = realloc(arg_list, (sizeof(char*))*(arg_list_size));
arg_list[arg_list_size] = malloc(sizeof(char*));
arg_list[arg_list_size] = (char*)NULL;
return arg_list;
}
/*
* Ruby classes and functions
*/
VALUE rb_execute_sh(VALUE self, VALUE rb_stdin, VALUE rb_timeout, VALUE rb_command) {
int stdin_ends[2];
int stdout_ends[2];
int stderr_ends[2];
if(pipe(stdin_ends) == -1 || pipe(stdout_ends) == -1 || pipe(stderr_ends) == -1) {
rb_raise(sse_PipeFailureError, "%s:%d (%d) pipe: %s\n", __FILE__, __LINE__, errno, strerror(errno));
}
char **command_list = split(StringValueCStr(rb_command), (char*)" ");
char *stdin_buf = StringValueCStr(rb_stdin);
pid_t pid = fork();
if(pid > 0) {
size_t stdout_buf_size = 0;
size_t stderr_buf_size = 0;
size_t stdout_buf_max = 1;
size_t stderr_buf_max = 1;
char *stdout_buf = malloc(1);
char *stderr_buf = malloc(1);
stdout_buf[0] = '\0';
stderr_buf[0] = '\0';
time_t start = time(NULL);
time_t timeout = NUM2INT(rb_timeout);
int sent_stdin = 0;
close(stdin_ends[0]);
close(stdout_ends[1]);
close(stderr_ends[1]);
while(difftime(time(NULL), start) < timeout) {
int status = waitpid(pid, NULL, WNOHANG);
if(status == -1) {
rb_raise(sse_WaitpidFailureError, "%s:%d (%d) waitpid: %s\n", __FILE__, __LINE__, errno, strerror(errno));
} else if(status == 0) {
fd_set write_set;
fd_set read_set;
struct timeval select_timeout = { 0, 0 };
int maxfd = (stdin_ends[1] > stdout_ends[0] ? (stdin_ends[1] > stderr_ends[0] ? stdin_ends[1] : stderr_ends[0]) : (stdout_ends[0] > stderr_ends[0] ? stdout_ends[0] : stderr_ends[0]));
FD_ZERO(&write_set);
FD_ZERO(&read_set);
if(sent_stdin == 0) {
FD_SET(stdin_ends[1], &write_set);
}
FD_SET(stdout_ends[0], &read_set);
FD_SET(stderr_ends[0], &read_set);
select(maxfd+1, &read_set, &write_set, NULL, &select_timeout);
if(FD_ISSET(stdin_ends[1], &write_set)) {
sent_stdin = 1;
if(write(stdin_ends[1], stdin_buf, strlen(stdin_buf)) == -1) {
rb_raise(sse_WriteFailureError, "%s:%d (%d) write: %s\n", __FILE__, __LINE__, errno, strerror(errno));
}
close(stdin_ends[1]);
}
if(FD_ISSET(stdout_ends[0], &read_set)) {
char tmp_buf[251];
ssize_t bytes_read = read(stdout_ends[0], tmp_buf, 250);
if(bytes_read == -1) {
rb_raise(sse_ReadFailureError, "%s:%d (%d) read: %s\n", __FILE__, __LINE__, errno, strerror(errno));
}
tmp_buf[bytes_read] = '\0';
while((stdout_buf_size + bytes_read+1) >= stdout_buf_max) {
stdout_buf_max *= 2;
stdout_buf = realloc(stdout_buf, stdout_buf_max);
}
strncpy(stdout_buf, tmp_buf, bytes_read);
stdout_buf_size += bytes_read;
stdout_buf[stdout_buf_size] = '\0';
}
if(FD_ISSET(stderr_ends[0], &read_set)) {
char tmp_buf[251];
ssize_t bytes_read = read(stderr_ends[0], tmp_buf, 250);
if(bytes_read == -1) {
rb_raise(sse_ReadFailureError, "%s:%d (%d) read: %s\n", __FILE__, __LINE__, errno, strerror(errno));
}
tmp_buf[bytes_read] = '\0';
while((stderr_buf_size + bytes_read+1) >= stderr_buf_max) {
stderr_buf_max *= 2;
stderr_buf = realloc(stderr_buf, stderr_buf_max);
}
strncpy(stderr_buf, tmp_buf, bytes_read);
stderr_buf_size += bytes_read;
stderr_buf[stderr_buf_size] = '\0';
}
} else {
close(stdout_ends[0]);
close(stderr_ends[1]);
VALUE result = rb_ary_new2(3);
rb_ary_store(result, 0, INT2NUM(difftime(time(NULL), start)));
rb_ary_store(result, 1, rb_str_new_cstr(stdout_buf));
rb_ary_store(result, 2, rb_str_new_cstr(stderr_buf));
return result;
}
}
kill(SIGINT, pid);
rb_raise(sse_TimeoutError, "Proccess took too long to finish.\n");
} else if(pid == 0) {
dup2(stdin_ends[0], STDIN_FILENO);
dup2(stdout_ends[1], STDOUT_FILENO);
dup2(stderr_ends[1], STDERR_FILENO);
close(stdin_ends[1]);
close(stdout_ends[0]);
close(stderr_ends[0]);
if(execvp(command_list[0], command_list) == -1) {
rb_raise(sse_ForkFailureError, "%s:%d (%d) execvp: %s\n", __FILE__, __LINE__, errno, strerror(errno));
}
} else {
rb_raise(sse_FileNotFoundError, "%s:%d (%d) execvp: %s\n", __FILE__, __LINE__, errno, strerror(errno));
}
VALUE thunderfury_blessed_blade_of_the_windseeker = rb_ary_new2(3);
rb_ary_store(thunderfury_blessed_blade_of_the_windseeker, 0, INT2NUM(42));
rb_ary_store(thunderfury_blessed_blade_of_the_windseeker, 1, rb_str_new_cstr("this is stdout"));
rb_ary_store(thunderfury_blessed_blade_of_the_windseeker, 2, rb_str_new_cstr("this is stderr"));
return thunderfury_blessed_blade_of_the_windseeker;
}
/*
* Initialize the module
*/
void Init_sse() {
sse_module = rb_define_module("sse");
sse_FileNotFoundError = rb_define_class_under(sse_module, "FileNotFoundError", rb_eStandardError);
sse_ForkFailureError = rb_define_class_under(sse_module, "ForkFailureError", rb_eStandardError);
sse_PipeFailureError = rb_define_class_under(sse_module, "PipeFailureError", rb_eStandardError);
sse_WriteFailureError = rb_define_class_under(sse_module, "WriteFailureError", rb_eStandardError);
sse_ReadFailureError = rb_define_class_under(sse_module, "ReadFailureError", rb_eStandardError);
sse_WaitpidFailureError = rb_define_class_under(sse_module, "WaitpidFailureError", rb_eStandardError);
sse_TimeoutError = rb_define_class_under(sse_module, "TimeoutError", rb_eStandardError);
rb_define_global_function("execute_sh", rb_execute_sh, 3);
}
When running it from a script, it works great:
admins-MacBook-Pro-2:sse-ruby nchambers$ cat client.rb
require './sse'
result = execute_sh('', 10, 'hostname')
puts "=>#{result[0]}<=\n=>#{result[1]}<=\n=>#{result[2]}<=\n"
admins-MacBook-Pro-2:sse-ruby nchambers$ ruby client.rb
=>0<=
=>admins-MacBook-Pro-2.local
<=
=><=
admins-MacBook-Pro-2:sse-ruby nchambers$
However, if I do the same thing from irb, I get this:
admins-MacBook-Pro-2:sse-ruby nchambers$ irb
2.2.4 :001 > require './sse'
=> true
2.2.4 :002 > result = execute_sh('', 10, 'hostname')
=> [0, "\n.2.4 :003 > :in `execute_sh'\n\tfrom (irb):2\n\tfrom /Users/nchambers/.rvm/rubies/ruby-2.2.4/bin/irb:11:in `<main>'\n", "irb(6804,0x7fffa88db3c0) malloc: *** error for object 0x7ff9ece81880: pointer being freed was not allocated\n*** set a breakpoint in malloc_error_break to debug\n"]
2.2.4 :003 > puts "=>#{result[0]}<=\n=>#{result[1]}<=\n=>#{result[2]}<=\n"
=>0<=
=>
.2.4 :003 > :in `execute_sh'
from (irb):2
from /Users/nchambers/.rvm/rubies/ruby-2.2.4/bin/irb:11:in `<main>'
<=
=>irb(6804,0x7fffa88db3c0) malloc: *** error for object 0x7ff9ece81880: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
<=
=> nil
2.2.4 :004 >
I can't see any reason why that would happen. So my question is, why does IRB fail where the script succeeds? Thank you!
arg_list[0] = malloc(strlen(arg));
strncpy(arg_list[0], arg, strlen(arg));
arg_list[arg_list_size] = malloc(strlen(arg));
strncpy(arg_list[arg_list_size], arg, strlen(arg));
no
arg_list[0] = malloc(strlen(arg) + 1);
strncpy(arg_list[0], arg, strlen(arg) + 1);
arg_list[0][strlen(arg)] = '\0';
arg_list[arg_list_size] = malloc(strlen(arg) + 1);
strncpy(arg_list[arg_list_size], arg, strlen(arg) + 1);
arg_list[arg_list_size][strlen(arg)] = '\0';
technically works
arg_list[0] = strdup(arg);
arg_list[arg_list_size] = strdup(arg);
it’s okay I guess
that’ll probably do what you think you want but is not a complete fix for the underlying problem, namely the C

Resources