LCOV - code coverage report
Current view: top level - source3/torture - test_messaging_read.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 302 413 73.1 %
Date: 2024-04-21 15:09:00 Functions: 16 17 94.1 %

          Line data    Source code
       1             : /*
       2             :    Unix SMB/CIFS implementation.
       3             :    Test for a messaging_read bug
       4             :    Copyright (C) Volker Lendecke 2014
       5             : 
       6             :    This program is free software; you can redistribute it and/or modify
       7             :    it under the terms of the GNU General Public License as published by
       8             :    the Free Software Foundation; either version 3 of the License, or
       9             :    (at your option) any later version.
      10             : 
      11             :    This program is distributed in the hope that it will be useful,
      12             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      13             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      14             :    GNU General Public License for more details.
      15             : 
      16             :    You should have received a copy of the GNU General Public License
      17             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      18             : */
      19             : 
      20             : #include "includes.h"
      21             : #include "torture/proto.h"
      22             : #include "lib/util/tevent_unix.h"
      23             : #include "messages.h"
      24             : 
      25             : struct msg_count_state {
      26             :         struct tevent_context *ev;
      27             :         struct messaging_context *msg_ctx;
      28             :         uint32_t msg_type;
      29             :         unsigned *count;
      30             : };
      31             : 
      32             : static void msg_count_done(struct tevent_req *subreq);
      33             : 
      34           3 : static struct tevent_req *msg_count_send(TALLOC_CTX *mem_ctx,
      35             :                                          struct tevent_context *ev,
      36             :                                          struct messaging_context *msg_ctx,
      37             :                                          uint32_t msg_type,
      38             :                                          unsigned *count)
      39             : {
      40           3 :         struct tevent_req *req, *subreq;
      41           3 :         struct msg_count_state *state;
      42             : 
      43           3 :         req = tevent_req_create(mem_ctx, &state, struct msg_count_state);
      44           3 :         if (req == NULL) {
      45           0 :                 return NULL;
      46             :         }
      47           3 :         state->ev = ev;
      48           3 :         state->msg_ctx = msg_ctx;
      49           3 :         state->msg_type = msg_type;
      50           3 :         state->count = count;
      51             : 
      52           3 :         subreq = messaging_read_send(state, state->ev, state->msg_ctx,
      53           0 :                                      state->msg_type);
      54           3 :         if (tevent_req_nomem(subreq, req)) {
      55           0 :                 return tevent_req_post(req, ev);
      56             :         }
      57           3 :         tevent_req_set_callback(subreq, msg_count_done, req);
      58           3 :         return req;
      59             : }
      60             : 
      61           1 : static void msg_count_done(struct tevent_req *subreq)
      62             : {
      63           1 :         struct tevent_req *req = tevent_req_callback_data(
      64             :                 subreq, struct tevent_req);
      65           1 :         struct msg_count_state *state = tevent_req_data(
      66             :                 req, struct msg_count_state);
      67           1 :         int ret;
      68             : 
      69           1 :         ret = messaging_read_recv(subreq, NULL, NULL);
      70           1 :         TALLOC_FREE(subreq);
      71           1 :         if (tevent_req_error(req, ret)) {
      72           0 :                 return;
      73             :         }
      74           1 :         *state->count += 1;
      75             : 
      76           1 :         subreq = messaging_read_send(state, state->ev, state->msg_ctx,
      77             :                                      state->msg_type);
      78           1 :         if (tevent_req_nomem(subreq, req)) {
      79           0 :                 return;
      80             :         }
      81           1 :         tevent_req_set_callback(subreq, msg_count_done, req);
      82             : }
      83             : 
      84           1 : bool run_messaging_read1(int dummy)
      85             : {
      86           1 :         struct tevent_context *ev = NULL;
      87           1 :         struct messaging_context *msg_ctx = NULL;
      88           1 :         struct tevent_req *req1 = NULL;
      89           1 :         unsigned count1 = 0;
      90           1 :         struct tevent_req *req2 = NULL;
      91           1 :         unsigned count2 = 0;
      92           1 :         NTSTATUS status;
      93           1 :         bool retval = false;
      94           1 :         int i;
      95             : 
      96           1 :         ev = samba_tevent_context_init(talloc_tos());
      97           1 :         if (ev == NULL) {
      98           0 :                 fprintf(stderr, "tevent_context_init failed\n");
      99           0 :                 goto fail;
     100             :         }
     101           1 :         msg_ctx = messaging_init(ev, ev);
     102           1 :         if (msg_ctx == NULL) {
     103           0 :                 fprintf(stderr, "messaging_init failed\n");
     104           0 :                 goto fail;
     105             :         }
     106             : 
     107           1 :         req1 = msg_count_send(ev, ev, msg_ctx, MSG_SMB_NOTIFY, &count1);
     108           1 :         if (req1 == NULL) {
     109           0 :                 fprintf(stderr, "msg_count_send failed\n");
     110           0 :                 goto fail;
     111             :         }
     112           1 :         req2 = msg_count_send(ev, ev, msg_ctx, MSG_SMB_NOTIFY, &count2);
     113           1 :         if (req1 == NULL) {
     114           0 :                 fprintf(stderr, "msg_count_send failed\n");
     115           0 :                 goto fail;
     116             :         }
     117           1 :         status = messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
     118             :                                     MSG_SMB_NOTIFY, NULL, 0);
     119           1 :         if (!NT_STATUS_IS_OK(status)) {
     120           0 :                 fprintf(stderr, "messaging_send_buf failed: %s\n",
     121             :                         nt_errstr(status));
     122           0 :                 goto fail;
     123             :         }
     124             : 
     125           3 :         for (i=0; i<2; i++) {
     126           2 :                 if (tevent_loop_once(ev) != 0) {
     127           0 :                         fprintf(stderr, "tevent_loop_once failed\n");
     128           0 :                         goto fail;
     129             :                 }
     130             :         }
     131             : 
     132           1 :         printf("%u/%u\n", count1, count2);
     133             : 
     134           1 :         if ((count1 != 1) || (count2 != 0)) {
     135           0 :                 fprintf(stderr, "Got %u/%u msgs, expected 1/0\n",
     136             :                         count1, count2);
     137           0 :                 goto fail;
     138             :         }
     139             : 
     140           0 :         retval = true;
     141           1 : fail:
     142           1 :         TALLOC_FREE(req1);
     143           1 :         TALLOC_FREE(req2);
     144           1 :         TALLOC_FREE(msg_ctx);
     145           1 :         TALLOC_FREE(ev);
     146           1 :         return retval;
     147             : }
     148             : 
     149             : struct msg_free_state {
     150             :         struct tevent_req **to_free;
     151             : };
     152             : 
     153             : static void msg_free_done(struct tevent_req *subreq);
     154             : 
     155           1 : static struct tevent_req *msg_free_send(TALLOC_CTX *mem_ctx,
     156             :                                         struct tevent_context *ev,
     157             :                                         struct messaging_context *msg_ctx,
     158             :                                         uint32_t msg_type,
     159             :                                         struct tevent_req **to_free)
     160             : {
     161           1 :         struct tevent_req *req, *subreq;
     162           1 :         struct msg_free_state *state;
     163             : 
     164           1 :         req = tevent_req_create(mem_ctx, &state, struct msg_free_state);
     165           1 :         if (req == NULL) {
     166           0 :                 return NULL;
     167             :         }
     168           1 :         state->to_free = to_free;
     169             : 
     170           1 :         subreq = messaging_read_send(state, ev, msg_ctx, msg_type);
     171           1 :         if (tevent_req_nomem(subreq, req)) {
     172           0 :                 return tevent_req_post(req, ev);
     173             :         }
     174           1 :         tevent_req_set_callback(subreq, msg_free_done, req);
     175           1 :         return req;
     176             : }
     177             : 
     178           1 : static void msg_free_done(struct tevent_req *subreq)
     179             : {
     180           1 :         struct tevent_req *req = tevent_req_callback_data(
     181             :                 subreq, struct tevent_req);
     182           1 :         struct msg_free_state *state = tevent_req_data(
     183             :                 req, struct msg_free_state);
     184           1 :         int ret;
     185             : 
     186           1 :         ret = messaging_read_recv(subreq, NULL, NULL);
     187           1 :         TALLOC_FREE(subreq);
     188           1 :         if (tevent_req_error(req, ret)) {
     189           0 :                 return;
     190             :         }
     191           1 :         TALLOC_FREE(*state->to_free);
     192           1 :         tevent_req_done(req);
     193             : }
     194             : 
     195           1 : bool run_messaging_read2(int dummy)
     196             : {
     197           1 :         struct tevent_context *ev = NULL;
     198           1 :         struct messaging_context *msg_ctx = NULL;
     199           1 :         struct tevent_req *req1 = NULL;
     200           1 :         struct tevent_req *req2 = NULL;
     201           1 :         unsigned count = 0;
     202           1 :         NTSTATUS status;
     203           1 :         bool retval = false;
     204             : 
     205           1 :         ev = samba_tevent_context_init(talloc_tos());
     206           1 :         if (ev == NULL) {
     207           0 :                 fprintf(stderr, "tevent_context_init failed\n");
     208           0 :                 goto fail;
     209             :         }
     210           1 :         msg_ctx = messaging_init(ev, ev);
     211           1 :         if (msg_ctx == NULL) {
     212           0 :                 fprintf(stderr, "messaging_init failed\n");
     213           0 :                 goto fail;
     214             :         }
     215             : 
     216           1 :         req1 = msg_free_send(ev, ev, msg_ctx, MSG_SMB_NOTIFY, &req2);
     217           1 :         if (req1 == NULL) {
     218           0 :                 fprintf(stderr, "msg_count_send failed\n");
     219           0 :                 goto fail;
     220             :         }
     221           1 :         req2 = msg_count_send(ev, ev, msg_ctx, MSG_SMB_NOTIFY, &count);
     222           1 :         if (req1 == NULL) {
     223           0 :                 fprintf(stderr, "msg_count_send failed\n");
     224           0 :                 goto fail;
     225             :         }
     226           1 :         status = messaging_send_buf(msg_ctx, messaging_server_id(msg_ctx),
     227             :                                     MSG_SMB_NOTIFY, NULL, 0);
     228           1 :         if (!NT_STATUS_IS_OK(status)) {
     229           0 :                 fprintf(stderr, "messaging_send_buf failed: %s\n",
     230             :                         nt_errstr(status));
     231           0 :                 goto fail;
     232             :         }
     233             : 
     234           1 :         if (!tevent_req_poll(req1, ev) != 0) {
     235           0 :                 fprintf(stderr, "tevent_req_poll failed\n");
     236           0 :                 goto fail;
     237             :         }
     238             : 
     239           1 :         if (count != 0) {
     240           0 :                 fprintf(stderr, "Got %u msgs, expected none\n", count);
     241           0 :                 goto fail;
     242             :         }
     243             : 
     244           0 :         retval = true;
     245           1 : fail:
     246           1 :         TALLOC_FREE(req1);
     247           1 :         TALLOC_FREE(msg_ctx);
     248           1 :         TALLOC_FREE(ev);
     249           1 :         return retval;
     250             : }
     251             : 
     252             : struct msg_pingpong_state {
     253             :         struct messaging_context *msg_ctx;
     254             : };
     255             : 
     256             : static void msg_pingpong_done(struct tevent_req *subreq);
     257             : 
     258         100 : static struct tevent_req *msg_pingpong_send(TALLOC_CTX *mem_ctx,
     259             :                                             struct tevent_context *ev,
     260             :                                             struct server_id dst)
     261             : {
     262         100 :         struct tevent_req *req, *subreq;
     263         100 :         struct msg_pingpong_state *state;
     264         100 :         NTSTATUS status;
     265             : 
     266         100 :         req = tevent_req_create(mem_ctx, &state, struct msg_pingpong_state);
     267         100 :         if (req == NULL) {
     268           0 :                 return NULL;
     269             :         }
     270             : 
     271         100 :         if (!tevent_req_set_endtime(req, ev, timeval_current_ofs(10, 0))) {
     272           0 :                 return tevent_req_post(req, ev);
     273             :         }
     274             : 
     275         100 :         state->msg_ctx = messaging_init(state, ev);
     276         100 :         if (tevent_req_nomem(state->msg_ctx, req)) {
     277           0 :                 return tevent_req_post(req, ev);
     278             :         }
     279             : 
     280         100 :         status = messaging_send_buf(state->msg_ctx, dst, MSG_PING, NULL, 0);
     281         100 :         if (!NT_STATUS_IS_OK(status)) {
     282           0 :                 DBG_DEBUG("messaging_send_buf failed: %s\n", nt_errstr(status));
     283           0 :                 tevent_req_error(req, map_errno_from_nt_status(status));
     284           0 :                 return tevent_req_post(req, ev);
     285             :         }
     286             : 
     287         100 :         subreq = messaging_read_send(state, ev, state->msg_ctx, MSG_PONG);
     288         100 :         if (tevent_req_nomem(subreq, req)) {
     289           0 :                 return tevent_req_post(req, ev);
     290             :         }
     291         100 :         tevent_req_set_callback(subreq, msg_pingpong_done, req);
     292         100 :         return req;
     293             : }
     294             : 
     295         100 : static void msg_pingpong_done(struct tevent_req *subreq)
     296             : {
     297         100 :         struct tevent_req *req = tevent_req_callback_data(
     298             :                 subreq, struct tevent_req);
     299         100 :         int ret;
     300             : 
     301         100 :         ret = messaging_read_recv(subreq, NULL, NULL);
     302         100 :         TALLOC_FREE(subreq);
     303         100 :         if (ret != 0) {
     304           0 :                 tevent_req_error(req, ret);
     305           0 :                 return;
     306             :         }
     307         100 :         tevent_req_done(req);
     308             : }
     309             : 
     310         100 : static int msg_pingpong_recv(struct tevent_req *req)
     311             : {
     312         100 :         int err;
     313             : 
     314         100 :         if (tevent_req_is_unix_error(req, &err)) {
     315           0 :                 return err;
     316             :         }
     317           0 :         return 0;
     318             : }
     319             : 
     320         100 : static int msg_pingpong(struct server_id dst)
     321             : {
     322         100 :         struct tevent_context *ev;
     323         100 :         struct tevent_req *req;
     324         100 :         int ret = ENOMEM;
     325             : 
     326         100 :         ev = tevent_context_init(talloc_tos());
     327         100 :         if (ev == NULL) {
     328           0 :                 goto fail;
     329             :         }
     330         100 :         req = msg_pingpong_send(ev, ev, dst);
     331         100 :         if (req == NULL) {
     332           0 :                 goto fail;
     333             :         }
     334         100 :         if (!tevent_req_poll(req, ev)) {
     335           0 :                 ret = errno;
     336           0 :                 goto fail;
     337             :         }
     338         200 :         ret = msg_pingpong_recv(req);
     339         100 : fail:
     340         100 :         TALLOC_FREE(ev);
     341         100 :         return ret;
     342             : }
     343             : 
     344           1 : static void ping_responder_exit(struct tevent_context *ev,
     345             :                                 struct tevent_fd *fde,
     346             :                                 uint16_t flags,
     347             :                                 void *private_data)
     348             : {
     349           1 :         bool *done = private_data;
     350             : 
     351           1 :         printf("Child: received write on exit-pipe\n");
     352             : 
     353           1 :         *done = true;
     354           1 : }
     355             : 
     356           1 : static void ping_responder(int ready_pipe, int exit_pipe)
     357             : {
     358           1 :         struct tevent_context *ev;
     359           1 :         struct messaging_context *msg_ctx;
     360           1 :         struct tevent_fd *exit_handler;
     361           1 :         char c = 0;
     362           1 :         bool done = false;
     363             : 
     364           1 :         ev = samba_tevent_context_init(talloc_tos());
     365           1 :         if (ev == NULL) {
     366           0 :                 fprintf(stderr, "child tevent_context_init failed\n");
     367           0 :                 exit(1);
     368             :         }
     369           1 :         msg_ctx = messaging_init(ev, ev);
     370           1 :         if (msg_ctx == NULL) {
     371           0 :                 fprintf(stderr, "child messaging_init failed\n");
     372           0 :                 exit(1);
     373             :         }
     374           1 :         exit_handler = tevent_add_fd(ev, ev, exit_pipe, TEVENT_FD_READ,
     375             :                                      ping_responder_exit, &done);
     376           1 :         if (exit_handler == NULL) {
     377           0 :                 fprintf(stderr, "child tevent_add_fd failed\n");
     378           0 :                 exit(1);
     379             :         }
     380             : 
     381           1 :         if (write(ready_pipe, &c, 1) != 1) {
     382           0 :                 fprintf(stderr, "child messaging_init failed\n");
     383           0 :                 exit(1);
     384             :         }
     385             : 
     386         102 :         while (!done) {
     387         101 :                 int ret;
     388         101 :                 ret = tevent_loop_once(ev);
     389         101 :                 if (ret != 0) {
     390           0 :                         fprintf(stderr, "child tevent_loop_once failed\n");
     391           0 :                         exit(1);
     392             :                 }
     393             :         }
     394             : 
     395           1 :         printf("Child: done, exiting...\n");
     396             : 
     397           1 :         TALLOC_FREE(msg_ctx);
     398           1 :         TALLOC_FREE(ev);
     399           1 : }
     400             : 
     401           1 : bool run_messaging_read3(int dummy)
     402             : {
     403           1 :         struct tevent_context *ev = NULL;
     404           1 :         struct messaging_context *msg_ctx = NULL;
     405           1 :         bool retval = false;
     406           1 :         pid_t child;
     407           1 :         int ready_pipe[2];
     408           1 :         int exit_pipe[2];
     409           1 :         int i, ret;
     410           1 :         char c;
     411           1 :         struct server_id dst;
     412           1 :         ssize_t written;
     413             : 
     414           1 :         if ((pipe(ready_pipe) != 0) || (pipe(exit_pipe) != 0)) {
     415           0 :                 perror("pipe failed");
     416           0 :                 return false;
     417             :         }
     418             : 
     419           1 :         child = fork();
     420           2 :         if (child == -1) {
     421           0 :                 perror("fork failed");
     422           0 :                 return false;
     423             :         }
     424             : 
     425           2 :         if (child == 0) {
     426           1 :                 close(ready_pipe[0]);
     427           1 :                 close(exit_pipe[1]);
     428           1 :                 ping_responder(ready_pipe[1], exit_pipe[0]);
     429           1 :                 exit(0);
     430             :         }
     431           1 :         close(ready_pipe[1]);
     432           1 :         close(exit_pipe[0]);
     433             : 
     434           1 :         if (read(ready_pipe[0], &c, 1) != 1) {
     435           0 :                 perror("read failed");
     436           0 :                 return false;
     437             :         }
     438             : 
     439           1 :         ev = samba_tevent_context_init(talloc_tos());
     440           1 :         if (ev == NULL) {
     441           0 :                 fprintf(stderr, "tevent_context_init failed\n");
     442           0 :                 goto fail;
     443             :         }
     444             : 
     445           1 :         dst = (struct server_id){ .pid = child, .vnn = NONCLUSTER_VNN, };
     446             : 
     447         101 :         for (i=0; i<100; i++) {
     448         100 :                 ret = msg_pingpong(dst);
     449         100 :                 if (ret != 0){
     450           0 :                         fprintf(stderr, "msg_pingpong failed\n");
     451           0 :                         goto fail;
     452             :                 }
     453             :         }
     454             : 
     455           1 :         printf("Parent: telling child to exit\n");
     456             : 
     457           1 :         written = write(exit_pipe[1], &c, 1);
     458           1 :         if (written != 1) {
     459           0 :                 perror("write to exit_pipe failed");
     460           0 :                 goto fail;
     461             :         }
     462             : 
     463           1 :         ret = waitpid(child, NULL, 0);
     464           1 :         if (ret == -1) {
     465           0 :                 perror("waitpid failed");
     466           0 :                 goto fail;
     467             :         }
     468             : 
     469           1 :         printf("Parent: child exited. Done\n");
     470             : 
     471           1 :         retval = true;
     472           1 : fail:
     473           1 :         TALLOC_FREE(msg_ctx);
     474           1 :         TALLOC_FREE(ev);
     475           0 :         return retval;
     476             : }
     477             : 
     478             : /**
     479             :  * read4:
     480             :  *
     481             :  * test transferring a big payload.
     482             :  */
     483             : 
     484             : #define MSG_TORTURE_READ4 0xF104
     485             : 
     486           1 : static bool read4_child(int ready_fd)
     487             : {
     488           1 :         struct tevent_context *ev = NULL;
     489           1 :         struct messaging_context *msg_ctx = NULL;
     490           1 :         TALLOC_CTX *frame = talloc_stackframe();
     491           1 :         bool retval = false;
     492           1 :         uint8_t c = 1;
     493           1 :         struct tevent_req *subreq;
     494           1 :         int ret;
     495           1 :         ssize_t bytes;
     496           1 :         struct messaging_rec *rec;
     497           1 :         bool ok;
     498             : 
     499           1 :         ev = samba_tevent_context_init(frame);
     500           1 :         if (ev == NULL) {
     501           0 :                 fprintf(stderr, "child: tevent_context_init failed\n");
     502           0 :                 goto done;
     503             :         }
     504             : 
     505           1 :         msg_ctx = messaging_init(ev, ev);
     506           1 :         if (msg_ctx == NULL) {
     507           0 :                 fprintf(stderr, "child: messaging_init failed\n");
     508           0 :                 goto done;
     509             :         }
     510             : 
     511           1 :         printf("child: telling parent we're ready to receive messages\n");
     512             : 
     513             :         /* Tell the parent we are ready to receive messages. */
     514           1 :         bytes = write(ready_fd, &c, 1);
     515           1 :         if (bytes != 1) {
     516           0 :                 perror("child: failed to write to ready_fd");
     517           0 :                 goto done;
     518             :         }
     519             : 
     520           1 :         printf("child: waiting for messages\n");
     521             : 
     522           1 :         subreq = messaging_read_send(frame, /* TALLOC_CTX */
     523             :                                      ev, msg_ctx,
     524             :                                      MSG_TORTURE_READ4);
     525           1 :         if (subreq == NULL) {
     526           0 :                 fprintf(stderr, "child: messaging_read_send failed\n");
     527           0 :                 goto done;
     528             :         }
     529             : 
     530           1 :         ok = tevent_req_poll(subreq, ev);
     531           1 :         if (!ok) {
     532           0 :                 fprintf(stderr, "child: tevent_req_poll failed\n");
     533           0 :                 goto done;
     534             :         }
     535             : 
     536           1 :         printf("child: receiving message\n");
     537             : 
     538           1 :         ret = messaging_read_recv(subreq, frame, &rec);
     539           1 :         TALLOC_FREE(subreq);
     540           1 :         if (ret != 0) {
     541           0 :                 fprintf(stderr, "child: messaging_read_recv failed\n");
     542           0 :                 goto done;
     543             :         }
     544             : 
     545           1 :         printf("child: received message\n");
     546             : 
     547             :         /* Tell the parent we are done. */
     548           1 :         bytes = write(ready_fd, &c, 1);
     549           1 :         if (bytes != 1) {
     550           0 :                 perror("child: failed to write to ready_fd");
     551           0 :                 goto done;
     552             :         }
     553             : 
     554           1 :         printf("child: done\n");
     555             : 
     556           1 :         retval = true;
     557             : 
     558           1 : done:
     559           1 :         TALLOC_FREE(frame);
     560           1 :         return retval;
     561             : }
     562             : 
     563             : struct child_done_state {
     564             :         int fd;
     565             :         bool done;
     566             : };
     567             : 
     568           1 : static void child_done_cb(struct tevent_context *ev,
     569             :                           struct tevent_fd *fde,
     570             :                           uint16_t flags,
     571             :                           void *private_data)
     572             : {
     573           1 :         struct child_done_state *state =
     574             :                         (struct child_done_state *)private_data;
     575           1 :         char c = 0;
     576           1 :         ssize_t bytes;
     577             : 
     578           1 :         bytes = read(state->fd, &c, 1);
     579           1 :         if (bytes != 1) {
     580           0 :                 perror("parent: read from ready_fd failed");
     581             :         }
     582             : 
     583           1 :         state->done = true;
     584           1 : }
     585             : 
     586           1 : static bool read4_parent(pid_t child_pid, int ready_fd)
     587             : {
     588           1 :         struct tevent_context *ev = NULL;
     589           1 :         struct messaging_context *msg_ctx = NULL;
     590           1 :         bool retval = false;
     591           1 :         int ret;
     592           1 :         NTSTATUS status;
     593           1 :         struct server_id dst;
     594           1 :         TALLOC_CTX *frame = talloc_stackframe();
     595           1 :         uint8_t c;
     596           1 :         ssize_t bytes;
     597           1 :         struct iovec iov;
     598           1 :         DATA_BLOB blob;
     599           1 :         struct tevent_fd *child_done_fde;
     600           1 :         struct child_done_state child_state;
     601             : 
     602             :         /* wait until the child is ready to receive messages */
     603           1 :         bytes = read(ready_fd, &c, 1);
     604           1 :         if (bytes != 1) {
     605           0 :                 perror("parent: read from ready_fd failed");
     606           0 :                 goto done;
     607             :         }
     608             : 
     609           1 :         printf("parent: child is ready to receive messages\n");
     610             : 
     611           1 :         ev = samba_tevent_context_init(frame);
     612           1 :         if (ev == NULL) {
     613           0 :                 fprintf(stderr, "parent: tevent_context_init failed\n");
     614           0 :                 goto done;
     615             :         }
     616             : 
     617           1 :         msg_ctx = messaging_init(ev, ev);
     618           1 :         if (msg_ctx == NULL) {
     619           0 :                 fprintf(stderr, "parent: messaging_init failed\n");
     620           0 :                 goto done;
     621             :         }
     622             : 
     623           1 :         child_state.fd = ready_fd;
     624           1 :         child_state.done = false;
     625             : 
     626           1 :         child_done_fde = tevent_add_fd(ev, ev, ready_fd, TEVENT_FD_READ,
     627             :                                        child_done_cb, &child_state);
     628           1 :         if (child_done_fde == NULL) {
     629           0 :                 fprintf(stderr,
     630             :                         "parent: failed tevent_add_fd for child done\n");
     631           0 :                 goto done;
     632             :         }
     633             : 
     634             :         /*
     635             :          * Send a 1M payload with the message.
     636             :          */
     637           1 :         blob = data_blob_talloc_zero(frame, 1000*1000);
     638           1 :         iov.iov_base = blob.data;
     639           1 :         iov.iov_len  = blob.length;
     640             : 
     641           1 :         dst = messaging_server_id(msg_ctx);
     642           1 :         dst.pid = child_pid;
     643             : 
     644           1 :         printf("parent: sending message to child\n");
     645             : 
     646           1 :         status = messaging_send_iov(msg_ctx, dst, MSG_TORTURE_READ4, &iov, 1,
     647             :                                     NULL, 0);
     648           1 :         if (!NT_STATUS_IS_OK(status)) {
     649           0 :                 fprintf(stderr, "parent: messaging_send_iov failed: %s\n",
     650             :                         nt_errstr(status));
     651           0 :                 goto done;
     652             :         }
     653             : 
     654           1 :         printf("parent: waiting for child to confirm\n");
     655             : 
     656        2961 :         while (!child_state.done) {
     657        2960 :                 ret = tevent_loop_once(ev);
     658        2960 :                 if (ret != 0) {
     659           0 :                         fprintf(stderr, "parent: tevent_loop_once failed\n");
     660           0 :                         goto done;
     661             :                 }
     662             :         }
     663             : 
     664           1 :         printf("parent: child confirmed\n");
     665             : 
     666           1 :         ret = waitpid(child_pid, NULL, 0);
     667           1 :         if (ret == -1) {
     668           0 :                 perror("parent: waitpid failed");
     669           0 :                 goto done;
     670             :         }
     671             : 
     672           1 :         printf("parent: done\n");
     673             : 
     674           1 :         retval = true;
     675             : 
     676           1 : done:
     677           1 :         TALLOC_FREE(frame);
     678           1 :         return retval;
     679             : }
     680             : 
     681           1 : bool run_messaging_read4(int dummy)
     682             : {
     683           1 :         bool retval = false;
     684           1 :         pid_t child_pid;
     685           1 :         int ready_pipe[2];
     686           1 :         int ret;
     687             : 
     688           1 :         ret = pipe(ready_pipe);
     689           1 :         if (ret != 0) {
     690           0 :                 perror("parent: pipe failed for ready_pipe");
     691           0 :                 return retval;
     692             :         }
     693             : 
     694           1 :         child_pid = fork();
     695           2 :         if (child_pid == -1) {
     696           0 :                 perror("fork failed");
     697           2 :         } else if (child_pid == 0) {
     698           1 :                 close(ready_pipe[0]);
     699           1 :                 retval = read4_child(ready_pipe[1]);
     700             :         } else {
     701           1 :                 close(ready_pipe[1]);
     702           1 :                 retval = read4_parent(child_pid, ready_pipe[0]);
     703             :         }
     704             : 
     705           0 :         return retval;
     706             : }

Generated by: LCOV version 1.14