| OLD | NEW | 
|    1 // Copyright 2014 The Crashpad Authors. All rights reserved. |    1 // Copyright 2014 The Crashpad Authors. All rights reserved. | 
|    2 // |    2 // | 
|    3 // Licensed under the Apache License, Version 2.0 (the "License"); |    3 // Licensed under the Apache License, Version 2.0 (the "License"); | 
|    4 // you may not use this file except in compliance with the License. |    4 // you may not use this file except in compliance with the License. | 
|    5 // You may obtain a copy of the License at |    5 // You may obtain a copy of the License at | 
|    6 // |    6 // | 
|    7 //     http://www.apache.org/licenses/LICENSE-2.0 |    7 //     http://www.apache.org/licenses/LICENSE-2.0 | 
|    8 // |    8 // | 
|    9 // Unless required by applicable law or agreed to in writing, software |    9 // Unless required by applicable law or agreed to in writing, software | 
|   10 // distributed under the License is distributed on an "AS IS" BASIS, |   10 // distributed under the License is distributed on an "AS IS" BASIS, | 
| (...skipping 10 matching lines...) Expand all  Loading... | 
|   21 #include "util/mac/launchd.h" |   21 #include "util/mac/launchd.h" | 
|   22 #include "util/misc/clock.h" |   22 #include "util/misc/clock.h" | 
|   23  |   23  | 
|   24 namespace crashpad { |   24 namespace crashpad { | 
|   25  |   25  | 
|   26 namespace { |   26 namespace { | 
|   27  |   27  | 
|   28 launch_data_t LaunchDataDictionaryForJob(const std::string& label) { |   28 launch_data_t LaunchDataDictionaryForJob(const std::string& label) { | 
|   29   base::mac::ScopedLaunchData request(LaunchDataAlloc(LAUNCH_DATA_DICTIONARY)); |   29   base::mac::ScopedLaunchData request(LaunchDataAlloc(LAUNCH_DATA_DICTIONARY)); | 
|   30   LaunchDataDictInsert( |   30   LaunchDataDictInsert( | 
|   31       request, LaunchDataNewString(label.c_str()), LAUNCH_KEY_GETJOB); |   31       request.get(), LaunchDataNewString(label.c_str()), LAUNCH_KEY_GETJOB); | 
|   32  |   32  | 
|   33   base::mac::ScopedLaunchData response(LaunchMsg(request)); |   33   base::mac::ScopedLaunchData response(LaunchMsg(request.get())); | 
|   34   if (LaunchDataGetType(response) != LAUNCH_DATA_DICTIONARY) { |   34   if (LaunchDataGetType(response.get()) != LAUNCH_DATA_DICTIONARY) { | 
|   35     return nullptr; |   35     return nullptr; | 
|   36   } |   36   } | 
|   37  |   37  | 
|   38   return response.release(); |   38   return response.release(); | 
|   39 } |   39 } | 
|   40  |   40  | 
|   41 }  // namespace |   41 }  // namespace | 
|   42  |   42  | 
|   43 bool ServiceManagementSubmitJob(CFDictionaryRef job_cf) { |   43 bool ServiceManagementSubmitJob(CFDictionaryRef job_cf) { | 
|   44   base::mac::ScopedLaunchData job_launch(CFPropertyToLaunchData(job_cf)); |   44   base::mac::ScopedLaunchData job_launch(CFPropertyToLaunchData(job_cf)); | 
|   45   if (!job_launch.get()) { |   45   if (!job_launch.get()) { | 
|   46     return false; |   46     return false; | 
|   47   } |   47   } | 
|   48  |   48  | 
|   49   base::mac::ScopedLaunchData jobs(LaunchDataAlloc(LAUNCH_DATA_ARRAY)); |   49   base::mac::ScopedLaunchData jobs(LaunchDataAlloc(LAUNCH_DATA_ARRAY)); | 
|   50   LaunchDataArraySetIndex(jobs, job_launch.release(), 0); |   50   LaunchDataArraySetIndex(jobs.get(), job_launch.release(), 0); | 
|   51  |   51  | 
|   52   base::mac::ScopedLaunchData request(LaunchDataAlloc(LAUNCH_DATA_DICTIONARY)); |   52   base::mac::ScopedLaunchData request(LaunchDataAlloc(LAUNCH_DATA_DICTIONARY)); | 
|   53   LaunchDataDictInsert(request, jobs.release(), LAUNCH_KEY_SUBMITJOB); |   53   LaunchDataDictInsert(request.get(), jobs.release(), LAUNCH_KEY_SUBMITJOB); | 
|   54  |   54  | 
|   55   base::mac::ScopedLaunchData response(LaunchMsg(request)); |   55   base::mac::ScopedLaunchData response(LaunchMsg(request.get())); | 
|   56   if (LaunchDataGetType(response) != LAUNCH_DATA_ARRAY) { |   56   if (LaunchDataGetType(response.get()) != LAUNCH_DATA_ARRAY) { | 
|   57     return false; |   57     return false; | 
|   58   } |   58   } | 
|   59  |   59  | 
|   60   if (LaunchDataArrayGetCount(response) != 1) { |   60   if (LaunchDataArrayGetCount(response.get()) != 1) { | 
|   61     return false; |   61     return false; | 
|   62   } |   62   } | 
|   63  |   63  | 
|   64   launch_data_t response_element = LaunchDataArrayGetIndex(response, 0); |   64   launch_data_t response_element = LaunchDataArrayGetIndex(response.get(), 0); | 
|   65   if (LaunchDataGetType(response_element) != LAUNCH_DATA_ERRNO) { |   65   if (LaunchDataGetType(response_element) != LAUNCH_DATA_ERRNO) { | 
|   66     return false; |   66     return false; | 
|   67   } |   67   } | 
|   68  |   68  | 
|   69   int err = LaunchDataGetErrno(response_element); |   69   int err = LaunchDataGetErrno(response_element); | 
|   70   if (err != 0) { |   70   if (err != 0) { | 
|   71     return false; |   71     return false; | 
|   72   } |   72   } | 
|   73  |   73  | 
|   74   return true; |   74   return true; | 
|   75 } |   75 } | 
|   76  |   76  | 
|   77 bool ServiceManagementRemoveJob(const std::string& label, bool wait) { |   77 bool ServiceManagementRemoveJob(const std::string& label, bool wait) { | 
|   78   base::mac::ScopedLaunchData request(LaunchDataAlloc(LAUNCH_DATA_DICTIONARY)); |   78   base::mac::ScopedLaunchData request(LaunchDataAlloc(LAUNCH_DATA_DICTIONARY)); | 
|   79   LaunchDataDictInsert( |   79   LaunchDataDictInsert( | 
|   80       request, LaunchDataNewString(label.c_str()), LAUNCH_KEY_REMOVEJOB); |   80       request.get(), LaunchDataNewString(label.c_str()), LAUNCH_KEY_REMOVEJOB); | 
|   81  |   81  | 
|   82   base::mac::ScopedLaunchData response(LaunchMsg(request)); |   82   base::mac::ScopedLaunchData response(LaunchMsg(request.get())); | 
|   83   if (LaunchDataGetType(response) != LAUNCH_DATA_ERRNO) { |   83   if (LaunchDataGetType(response.get()) != LAUNCH_DATA_ERRNO) { | 
|   84     return false; |   84     return false; | 
|   85   } |   85   } | 
|   86  |   86  | 
|   87   int err = LaunchDataGetErrno(response); |   87   int err = LaunchDataGetErrno(response.get()); | 
|   88   if (err == EINPROGRESS) { |   88   if (err == EINPROGRESS) { | 
|   89     if (wait) { |   89     if (wait) { | 
|   90       // TODO(mark): Use a kqueue to wait for the process to exit. To avoid a |   90       // TODO(mark): Use a kqueue to wait for the process to exit. To avoid a | 
|   91       // race, the kqueue would need to be set up prior to asking launchd to |   91       // race, the kqueue would need to be set up prior to asking launchd to | 
|   92       // remove the job. Even so, the job’s PID may change between the time it’s |   92       // remove the job. Even so, the job’s PID may change between the time it’s | 
|   93       // obtained and the time the kqueue is set up, so this is nontrivial. |   93       // obtained and the time the kqueue is set up, so this is nontrivial. | 
|   94       do { |   94       do { | 
|   95         SleepNanoseconds(1E5);  // 100 microseconds |   95         SleepNanoseconds(1E5);  // 100 microseconds | 
|   96       } while (ServiceManagementIsJobLoaded(label)); |   96       } while (ServiceManagementIsJobLoaded(label)); | 
|   97     } |   97     } | 
|   98  |   98  | 
|   99     return true; |   99     return true; | 
|  100   } |  100   } | 
|  101  |  101  | 
|  102   if (err != 0) { |  102   if (err != 0) { | 
|  103     return false; |  103     return false; | 
|  104   } |  104   } | 
|  105  |  105  | 
|  106   return true; |  106   return true; | 
|  107 } |  107 } | 
|  108  |  108  | 
|  109 bool ServiceManagementIsJobLoaded(const std::string& label) { |  109 bool ServiceManagementIsJobLoaded(const std::string& label) { | 
|  110   base::mac::ScopedLaunchData dictionary(LaunchDataDictionaryForJob(label)); |  110   base::mac::ScopedLaunchData dictionary(LaunchDataDictionaryForJob(label)); | 
|  111   if (!dictionary) { |  111   if (!dictionary.is_valid()) { | 
|  112     return false; |  112     return false; | 
|  113   } |  113   } | 
|  114  |  114  | 
|  115   return true; |  115   return true; | 
|  116 } |  116 } | 
|  117  |  117  | 
|  118 pid_t ServiceManagementIsJobRunning(const std::string& label) { |  118 pid_t ServiceManagementIsJobRunning(const std::string& label) { | 
|  119   base::mac::ScopedLaunchData dictionary(LaunchDataDictionaryForJob(label)); |  119   base::mac::ScopedLaunchData dictionary(LaunchDataDictionaryForJob(label)); | 
|  120   if (!dictionary) { |  120   if (!dictionary.is_valid()) { | 
|  121     return 0; |  121     return 0; | 
|  122   } |  122   } | 
|  123  |  123  | 
|  124   launch_data_t pid = LaunchDataDictLookup(dictionary, LAUNCH_JOBKEY_PID); |  124   launch_data_t pid = LaunchDataDictLookup(dictionary.get(), LAUNCH_JOBKEY_PID); | 
|  125   if (!pid) { |  125   if (!pid) { | 
|  126     return 0; |  126     return 0; | 
|  127   } |  127   } | 
|  128  |  128  | 
|  129   if (LaunchDataGetType(pid) != LAUNCH_DATA_INTEGER) { |  129   if (LaunchDataGetType(pid) != LAUNCH_DATA_INTEGER) { | 
|  130     return 0; |  130     return 0; | 
|  131   } |  131   } | 
|  132  |  132  | 
|  133   return LaunchDataGetInteger(pid); |  133   return LaunchDataGetInteger(pid); | 
|  134 } |  134 } | 
|  135  |  135  | 
|  136 }  // namespace crashpad |  136 }  // namespace crashpad | 
| OLD | NEW |