Spawn an RDB child that writes the RDB to the sockets of the slaves * that are currently in SLAVE_STATE_WAIT_BGSAVE_START state. */
| 2860 | /* Spawn an RDB child that writes the RDB to the sockets of the slaves |
| 2861 | * that are currently in SLAVE_STATE_WAIT_BGSAVE_START state. */ |
| 2862 | int rdbSaveToSlavesSockets(rdbSaveInfo *rsi) { |
| 2863 | listNode *ln; |
| 2864 | listIter li; |
| 2865 | pid_t childpid; |
| 2866 | int pipefds[2], rdb_pipe_write, safe_to_exit_pipe; |
| 2867 | |
| 2868 | if (hasActiveChildProcess()) return C_ERR; |
| 2869 | |
| 2870 | /* Even if the previous fork child exited, don't start a new one until we |
| 2871 | * drained the pipe. */ |
| 2872 | if (server.rdb_pipe_conns) return C_ERR; |
| 2873 | |
| 2874 | /* Before to fork, create a pipe that is used to transfer the rdb bytes to |
| 2875 | * the parent, we can't let it write directly to the sockets, since in case |
| 2876 | * of TLS we must let the parent handle a continuous TLS state when the |
| 2877 | * child terminates and parent takes over. */ |
| 2878 | if (pipe(pipefds) == -1) return C_ERR; |
| 2879 | server.rdb_pipe_read = pipefds[0]; /* read end */ |
| 2880 | rdb_pipe_write = pipefds[1]; /* write end */ |
| 2881 | anetNonBlock(NULL, server.rdb_pipe_read); |
| 2882 | |
| 2883 | /* create another pipe that is used by the parent to signal to the child |
| 2884 | * that it can exit. */ |
| 2885 | if (pipe(pipefds) == -1) { |
| 2886 | close(rdb_pipe_write); |
| 2887 | close(server.rdb_pipe_read); |
| 2888 | return C_ERR; |
| 2889 | } |
| 2890 | safe_to_exit_pipe = pipefds[0]; /* read end */ |
| 2891 | server.rdb_child_exit_pipe = pipefds[1]; /* write end */ |
| 2892 | |
| 2893 | /* Collect the connections of the replicas we want to transfer |
| 2894 | * the RDB to, which are i WAIT_BGSAVE_START state. */ |
| 2895 | server.rdb_pipe_conns = zmalloc(sizeof(connection *)*listLength(server.slaves)); |
| 2896 | server.rdb_pipe_numconns = 0; |
| 2897 | server.rdb_pipe_numconns_writing = 0; |
| 2898 | listRewind(server.slaves,&li); |
| 2899 | while((ln = listNext(&li))) { |
| 2900 | client *slave = ln->value; |
| 2901 | if (slave->replstate == SLAVE_STATE_WAIT_BGSAVE_START) { |
| 2902 | server.rdb_pipe_conns[server.rdb_pipe_numconns++] = slave->conn; |
| 2903 | replicationSetupSlaveForFullResync(slave,getPsyncInitialOffset()); |
| 2904 | } |
| 2905 | } |
| 2906 | |
| 2907 | /* Create the child process. */ |
| 2908 | if ((childpid = redisFork(CHILD_TYPE_RDB)) == 0) { |
| 2909 | /* Child */ |
| 2910 | int retval, dummy; |
| 2911 | rio rdb; |
| 2912 | |
| 2913 | rioInitWithFd(&rdb,rdb_pipe_write); |
| 2914 | |
| 2915 | redisSetProcTitle("redis-rdb-to-slaves"); |
| 2916 | redisSetCpuAffinity(server.bgsave_cpulist); |
| 2917 | |
| 2918 | retval = rdbSaveRioWithEOFMark(&rdb,NULL,rsi); |
| 2919 | if (retval == C_OK && rioFlush(&rdb) == 0) |
no test coverage detected