Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/63.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C中的分叉线程正在相互写入标准输出_C_Multithreading - Fatal编程技术网

C中的分叉线程正在相互写入标准输出

C中的分叉线程正在相互写入标准输出,c,multithreading,C,Multithreading,我写了一个小精灵 通常,这是守护进程的流程: 获取变量 从数据库(可能是MySQL或Oracle)中获取满足查询参数的所有行(在本例中,获取具有当前时间的所有行) 如果找到任何行,则为每行运行一个Perl脚本(使用execv) 这个守护进程工作得很好,但问题是当查询返回两行或更多行时,它们会启动,但Perl脚本输出是混合的。它们应该独立运行,互不干扰 我做错什么了吗 这是内存泄漏吗 这是我的密码: /* =============================================

我写了一个小精灵

通常,这是守护进程的流程:

  • 获取变量

  • 从数据库(可能是MySQL或Oracle)中获取满足查询参数的所有行(在本例中,获取具有当前时间的所有行)

  • 如果找到任何行,则为每行运行一个Perl脚本(使用execv)

  • 这个守护进程工作得很好,但问题是当查询返回两行或更多行时,它们会启动,但Perl脚本输出是混合的。它们应该独立运行,互不干扰

    我做错什么了吗

    这是内存泄漏吗

    这是我的密码:

    /*
     ============================================================================
     Name        : main.c
     Description : Daemon for scheduler
     ============================================================================
     */
    
    #include <sys/types.h>
    #include <sys/wait.h>
    #include <sys/stat.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <errno.h>
    #include <unistd.h>
    #include <syslog.h>
    #include <string.h>
    #include <strings.h>
    #include <regex.h>
    #include <time.h>
    
    #ifdef MYSQL_CODE
    #include <mysql.h>
    #endif
    
    #ifdef ORACLE_CODE
    #include <ocilib.h>
    #endif
    
    #define DAEMON_NAME "schedulerd"
    
    void start_job(char *automation_user,char *automation_path,char *automation_log_path, char *id, char *site, char *db_type,char *db_host,char *db_user,char *db_password,char *db_schemata){
    
        pid_t pid;
        pid = fork();
    
        if (pid < 0) { exit(EXIT_FAILURE); }
    
        //We got a good pid, Continue to the next result
        if (pid > 0) {
            return;
        }
    
        char *file_format = "scheduler";
        char *seperator = "_";
        char *postfix = "_XXXXXX";
        char *extension = ".log";
    
        //get Time
        time_t now;
        struct tm *now_tm;
        char hour[2],min[2],sec[2];
    
        now = time(NULL);
        now_tm = localtime(&now);
        sprintf(hour, "%d", now_tm->tm_hour);
        sprintf(min, "%d", now_tm->tm_min);
        sprintf(sec, "%d", now_tm->tm_sec);
    
        char *str  = (char *)automation_log_path;
        strcat(str,(char *)file_format);
        strcat(str,seperator);
        strcat(str,hour);
        strcat(str,seperator);
        strcat(str,min);
        strcat(str,seperator);
        strcat(str,sec);
        strcat(str,postfix);
    
        // buffer to hold the temporary file name
        char nameBuff[128];
    
        int filedes = -1;
    
        // memset the buffers to 0
        memset(nameBuff,0,sizeof(nameBuff));
    
        // Copy the relevant information in the buffers
        strncpy(nameBuff,str,128);
    
        // Create the temporary file, this function will replace the 'X's
        filedes = mkstemp(nameBuff);
    
        if(filedes<1)
        {
            syslog (LOG_NOTICE, "Creation of temp file [%s] failed with error [%s]\n",nameBuff,strerror(errno));
        }else{
            mode_t perm = 0644;
            fchmod(filedes, perm); //Change permission to the file so everyone can read
    
            close(filedes); // Close created file
            //Rename file
            int ret;
            char newname[128];
            sprintf(newname, "%s%s", nameBuff,extension);
            ret = rename(nameBuff, newname);
            if(ret != 0) {
                syslog (LOG_NOTICE, "Renaming  of temp file %s to %s failed \n",nameBuff,newname);
                exit(EXIT_FAILURE);
            }
    
            char statement[256];
            sprintf(statement, "UPDATE scheduler_list SET log_file='%s' WHERE id='%s'", newname,id);
            syslog (LOG_NOTICE,"Adding to DB : %s\n", statement);
    
            char command[2048];
            sprintf(command, "cd %s ; ./runner.pl -site %s -log %s -scheduler_id %s -command \\\"./run_me.pl\\\"", automation_path,site,newname,id);
            //sprintf(command, "cd /net/10.7.5.50/opt/trunk/ ; ./runner.pl -site %s -log %s -scheduler_id %s -command \\\"./run_me.pl\\\"",site,newname,id);
    
            if (strcasestr(db_type,"mysql")){/* mysql */
    #ifdef MYSQL_CODE
                MYSQL *conn;
                //mysql_free_result(res); // Free mysql
                conn = mysql_init(NULL);
                /* Connect to database */
                if (!mysql_real_connect(conn, db_host,db_user, db_password, db_schemata, 0, NULL, 0)) {
                    syslog (LOG_NOTICE,"%s\n", mysql_error(conn));
                    exit(EXIT_FAILURE);
                }
    
                if (mysql_query(conn,statement)) {
                    syslog (LOG_NOTICE,"%s\n", mysql_error(conn));
                    exit(EXIT_FAILURE);
                }
    #endif
            }else{
    #ifdef ORACLE_CODE
                OCI_Connection* cn;
                OCI_Statement* st;
                OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT);
                char query_command[128];
                sprintf(query_command, "%s:1521/%s", db_host,db_schemata);
                cn = OCI_ConnectionCreate(query_command, db_user, db_password, OCI_SESSION_DEFAULT);
                st = OCI_StatementCreate(cn);
                OCI_Prepare(st, statement);
                OCI_Execute(st);
                OCI_Commit(cn);
                OCI_Cleanup();
    #endif
            }
    
            char *args[] = {"sudo", "-u", automation_user, "bash","-c",command,NULL};
    
            FILE *log_file_h = fopen(newname, "w");
            if (log_file_h == NULL)
            {
                syslog (LOG_NOTICE,"Error opening file %s !\n",newname);
                exit(EXIT_FAILURE);
            }
    
            syslog (LOG_NOTICE,"Starting scheduler job %s , command : %s",id, command);
            fclose(log_file_h);
    
            execv("/usr/bin/sudo",args);
            syslog (LOG_NOTICE,"Failed to start job %s ",id);
            perror("error");
        }
        exit(EXIT_FAILURE);
    }
    
    void process(char *automation_user,char *automation_path, char *automation_log_path ,char *db_type,char *db_host,char *db_user,char *db_password,char *db_schemata){
    
        if (strcasestr(db_type,"mysql")){/* mysql */
    #ifdef MYSQL_CODE
            MYSQL *conn;
            MYSQL_RES *res;
            MYSQL_ROW row;
            conn = mysql_init(NULL);
            /* Connect to database */
            if (!mysql_real_connect(conn, db_host,db_user, db_password, db_schemata, 0, NULL, 0)) {
                syslog (LOG_NOTICE,"%s\n", mysql_error(conn));
                return;
            }
            /* send SQL query */
            if (mysql_query(conn, "SELECT id,site from scheduler_list where start_date = DATE_FORMAT(now(),'%Y-%m-%d %k:%i:00') AND id != father_id AND run='yes'")) {
                syslog (LOG_NOTICE,"%s\n", mysql_error(conn));
                return;
            }
            res = mysql_use_result(conn);
            /* output table name */
            while ((row = mysql_fetch_row(res)) != NULL){
                char *id = malloc(strlen(row[0]) +1);
                strcpy(id,row[0]);
                char *site = malloc(strlen(row[1]) +1);
                strcpy(site,row[1]);
    
                start_job(automation_user,automation_path,automation_log_path,id,site,db_type, db_host,db_user,db_password,db_schemata);
            }
            /* close connection */
            mysql_free_result(res);
            mysql_close(conn);
    #endif
        }else{/* oracle */
    #ifdef ORACLE_CODE
            OCI_Connection* cn;
            OCI_Statement* st;
            OCI_Resultset* rs;
            OCI_Initialize(NULL, NULL, OCI_ENV_DEFAULT);
            char query_command[128];
            sprintf(query_command, "%s:1521/%s", db_host,db_schemata);
            cn = OCI_ConnectionCreate(query_command, db_user, db_password, OCI_SESSION_DEFAULT);
            st = OCI_StatementCreate(cn);
    
            OCI_ExecuteStmt(st, "SELECT id,site from scheduler_list where to_char(start_date, 'yyyy-mm-dd hh24:mi')  =  to_char(SYSDATE, 'yyyy-mm-dd hh24:mi')  AND id != father_id AND run='yes'");
    
            rs = OCI_GetResultset(st);
            while (OCI_FetchNext(rs)){
    
                char *id = malloc(strlen(OCI_GetString(rs, 1)) +1);
                strcpy(id,OCI_GetString(rs,1));
                char *site = malloc(strlen(OCI_GetString(rs,2)) +1);
                strcpy(site,OCI_GetString(rs,2));
                start_job(automation_user,automation_path,automation_log_path,id,site,db_type, db_host,db_user,db_password,db_schemata);
            }
            OCI_Cleanup();
    #endif
        }
    
    
    }
    
    char * set_conf_param (char *line, int addSlash){
        char *param =  malloc(strlen(line) + 2 + addSlash);
        strcpy(param,line);
        param = strchr(line,'=');
        param = param+1; //Remove '='
        strtok(param, "\n"); //remove /n
        if (addSlash == 1){
            int len = strlen(param);
            param[len] = '/';
            param[len+1] = '\0';
        }
        return strdup(param);
    }
    
    int main(int argc, char *argv[]) {
            FILE * fp;
            char * line = NULL;
            size_t len = 0;
            int found_db = 0;
            ssize_t read;
            pid_t pid, sid;
            char *automation_user=NULL,*automation_log_path=NULL ,*db_type=NULL, *db_host=NULL , *db_user=NULL, *db_password=NULL, *db_schemata=NULL;
            char *automation_path = getenv("AUTOMATION_PATH");
            //char *automation_path = "/net/10.7.5.50/opt/trunk/";
    
            char *automation_user_search = "automation_user=";
            char *automation_log_path_search = "automation_log=";
            char *db_type_search = "type=";
            char *db_host_search = "host=";
            char *db_user_search = "user=";
            char *db_password_search = "password=";
            char *db_schemata_search = "schemata=";
            const char comment = '#';
            /* Change the working directory to the root directory */
            /* or another appropriated directory */
            chdir(automation_path);
    
            //Set our Logging Mask and open the Log
            setlogmask(LOG_UPTO(LOG_NOTICE));
            openlog(DAEMON_NAME, LOG_CONS | LOG_NDELAY | LOG_PERROR | LOG_PID, LOG_USER);
    
            syslog(LOG_NOTICE, "Entering Daemon");
    
            //Read framework.conf
            fp = fopen("framework.conf", "r");
            if (fp == NULL){
                syslog (LOG_NOTICE,"Failed to open framework.conf");
                exit(1);
            }
    
            //Read framework.conf
            fp = fopen("framework.conf", "r");
            if (fp == NULL){
                syslog (LOG_NOTICE,"Failed to open framework.conf");
                exit(1);
            }
            while ((read = getline(&line, &len, fp)) != -1) {
    
                //If line commented
                if (strchr(line,comment) != NULL){
                    continue;
                }
    
                if (strstr(line,automation_user_search) != NULL){
                    automation_user = set_conf_param(line,0);
                }
                else if (strstr(line,automation_log_path_search) != NULL){
                    automation_log_path = set_conf_param(line,1);
                }
    
                else if (db_type!=NULL && strcasestr(line,db_type) != NULL){
                    found_db = 1;
                }
                else if (strstr(line,db_type_search) != NULL){
                    db_type = set_conf_param(line,0);
                }
                else if (found_db && db_host==NULL && strstr(line,db_host_search) != NULL){
                    db_host = set_conf_param(line,0);
                }
                else if (found_db && db_user==NULL && strstr(line,db_user_search) != NULL){
                    db_user = set_conf_param(line,0);
                }
                else if (found_db && db_password==NULL && strstr(line,db_password_search) != NULL){
                    db_password = set_conf_param(line,0);
                }
                else if (found_db && db_schemata==NULL && strstr(line,db_schemata_search) != NULL){
                    db_schemata = set_conf_param(line,0);
                }
            }
    
            fclose(fp);
            if (line)
                free(line);
    
            if (automation_user==NULL){
                automation_user = "root";
            }
    
            //Fork the Parent Process
            pid = fork();
    
            if (pid < 0) { exit(EXIT_FAILURE); }
    
            //We got a good pid, Close the Parent Process
            if (pid > 0) { exit(EXIT_SUCCESS); }
    
            //Change File Mask
            umask(0);
    
            //Create a new Signature Id for our child
            sid = setsid();
            if (sid < 0) { exit(EXIT_FAILURE); }
    
            //Close Standard File Descriptors
            close(STDIN_FILENO);
            close(STDOUT_FILENO);
            close(STDERR_FILENO);
    
            //----------------
            //Main Process
            //----------------
            while(1){
                process(automation_user,automation_path,automation_log_path,db_type,db_host,db_user,db_password,db_schemata);    //Run our Process
                sleep(60);    //Sleep for 60 seconds
            }
    
            //Close the log
            closelog ();
    
            exit(EXIT_FAILURE);
    }
    
    /*
    ============================================================================
    姓名:main.c
    描述:调度程序的守护进程
    ============================================================================
    */
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #包括
    #ifdef MYSQL_代码
    #包括
    #恩迪夫
    #ifdef ORACLE_代码
    #包括
    #恩迪夫
    #定义守护程序名称“schedulerd”
    void start\u作业(char*automation\u user,char*automation\u path,char*automation\u log\u path,char*id,char*site,char*db_type,char*db\u host,char*db\u user,char*db\u密码,char*db\u schemata){
    pid_t pid;
    pid=fork();
    如果(pid<0){exit(exit_FAILURE);}
    //我们得到了一个很好的pid,继续下一个结果
    如果(pid>0){
    返回;
    }
    char*file_format=“调度器”;
    字符*分隔符=“25;”;
    char*postfix=“\uxxxxxx”;
    char*扩展名=“.log”;
    //有时间
    现在是时候了;
    struct tm*现在_tm;
    字符小时[2],分钟[2],秒[2];
    现在=时间(空);
    now_tm=本地时间(&now);
    sprintf(小时,“%d”,现在是\u tm->tm\u小时);
    sprintf(最小,“%d”,现在是\u tm->tm\u min);
    sprintf(秒,“%d”,现在为tm->tm秒);
    char*str=(char*)自动化日志路径;
    strcat(str,(char*)文件格式);
    strcat(str,分离器);
    strcat(str,小时);
    strcat(str,分离器);
    strcat(str,min);
    strcat(str,分离器);
    strcat(str,sec);
    strcat(str,后缀);
    //用于保存临时文件名的缓冲区
    char nameBuff[128];
    int filedes=-1;
    //mem将缓冲区设置为0
    memset(nameBuff,0,sizeof(nameBuff));
    //复制缓冲区中的相关信息
    strncpy(nameBuff,str,128);
    //创建临时文件,此函数将替换“X”
    filedes=mkstemp(nameBuff);
    if(filedes 0){exit(exit_SUCCESS);}
    //更改文件掩码
    乌马斯克(0);
    //为孩子创建一个新的签名Id
    sid=setsid();
    如果(sid<0){exit(exit_FAILURE);}
    //关闭标准文件描述符
    关闭(标准文件号);
    关闭(标准文件号);
    关闭(标准文件号);
    //----------------
    //主要过程
    //----------------
    而(1){
    进程(自动化用户、自动化路径、自动化日志路径、数据库类型、数据库主机、数据库用户、数据库密码、数据库模式);//运行我们的进程
    睡眠(60);//睡眠60秒
    }
    //关闭日志
    closelog();
    退出(退出失败);
    }
    
  • 你似乎没有努力写一篇文章

    这只是整个程序的转储,包括对未提供的配置文件的依赖关系,以及未显示其模式的数据库。这些都与你的问题无关

    至少您已经编辑掉了公司名称,但作为参考,它仍然可以在编辑历史记录中看到

  • C中的线程正在相互写入标准输出

    我在您的程序中看不到任何线程,而且您也没有分叉线程——您拥有的是子进程

  • 。。。你在互相写信吗

    嗯,stdout是从父级继承的,因此所有子级(以及它们的sudo/bash/perl/which子级)都在同一个位置写入。写入本身是锁定的,但可以交错进行

    如果您不希望它们的输出被交错,请让它们写入不同的位置,并找出以后如何显示/组合它们

    每个子进程临时文件是一种流行的选择,但请注意,父进程必须跟踪子进程的完成情况,以便知道何时打印并删除每个文件。此外,您可能应该从终端分离子进程,关闭STDIN,并考虑如何处理STDRR。

  • 这是内存泄漏吗

    没有

  • 你似乎没有努力写一篇文章

    这只是整个程序的转储,包括对未提供的配置文件的依赖关系,以及未显示其模式的数据库。这些都与你的问题无关

    至少您已经编辑掉了公司名称,但作为参考,它仍然可以在编辑历史记录中看到

  • C中的线程正在相互写入标准输出

    我在您的程序中看不到任何线程,而且您也没有分叉线程——您拥有的是子进程

  • 。。。你在互相写信吗

    嗯,stdout是从父级继承的,因此所有子级(以及它们的sudo/bash/perl/which子级)都在同一个位置写入。写入本身是锁定的,但可以交错进行

    如果您不希望它们的输出被交错,请让它们写入不同的位置,并找出以后如何显示/组合它们

    每个子进程临时文件是一种流行的选择,但请注意,父进程必须跟踪子进程的完成情况,以便知道何时打印并删除每个文件。此外,您可能应该从终端分离子进程,关闭STDIN,并考虑如何处理STDRR。

  • 这是内存泄漏吗

    没有

  • 我想(匆匆瞥了一眼)问题出在你身上了

    execv("/usr/bin/sudo",args);
    
    你应该确保只有一个我
    // create a global mutex variable
    pthread_mutex_t lock;
    
    // initialise it in main
    pthread_mutex_init(&lock, NULL);
    
    // enclose your critical path
    pthread_mutex_lock(&lock);
    execv("/usr/bin/sudo",args);
    pthread_mutex_unlock(&lock);